位图

来源:互联网 发布:软件开发项目进度表 编辑:程序博客网 时间:2024/04/30 11:57

STL里的位标识类,<bitset>

STL bitset是一个STL类,用于处理以位和位标志表示的信息,std::bitset不是STL容器类,因为它不能调整长度,也不具备容器的其他特征(见容器特征),如通过迭代器进行访问。这是一个实用类,针对处理长度在编译阶段已知的位序列进行了优化。

示例:

#include <iostream>#include <bitset>#include <string>int main(){bitset<8> eightBits;cout<<"The initial contents of fourBits:"<<eightBits<<endl;cout<<"Enter a 8-bits"<<endl;cin >> eightBits;cout<<endl;cout<<"The number of 1s in the input sequence"<<endl;cout<<eightBits.count()<<endl;cout<<"The number of 0s in the input sequence"<<endl;cout<<eightBits.size() - eightBits.count()<<endl;cout<<"bitset::flip:"<<endl;cout<<eightBits.flip()<<endl;cout<<"向右边移动两位"<<endl;eightBits>>=(2);//移位cout<<eightBits<<endl;cout<<"bitset::set(N,val = 1)"<<endl;eightBits.set(2,1);cout<<eightBits<<endl;cout<<"bitset::set()"<<endl;eightBits.set();//所有位置1cout<<eightBits<<endl;bitset<5> fiveBits(string("10101"));//bitset的初始化cout<<"The initial contents of fiveBits:"<<fiveBits<<endl;system("pause");return 0;}/*The initial contents of fourBits:00000000Enter a 8-bits11000101The number of 1s in the input sequence4The number of 0s in the input sequence4bitset::flip:00111010向右边移动两位00111010bitset::set(N,val = 1)00111110bitset::set()11111111The initial contents of fiveBits:10101请按任意键继续. . .*/


《编程珠玑》里c实现的位图

#include <stdio.h>#define N 10000000#define BITSPERWORD 32#define SHIFT 5#define MASK 0x1Fint arr[1 + N/BITSPERWORD];void set(int i){    arr[i>>SHIFT] |= (1<<(i&MASK));}int test(int i){    return arr[i>>SHIFT] & (1<<(i&MASK));}
转自http://www.cnblogs.com/shuaiwhu/archive/2011/05/29/2065039.html

整个程序的思想就是:
            1.每个整数有32位,那么它就可以表示32个数,分别对应每bit位为1.
            2.然后把10000000个数分为1+N/BITSPERWORD组(相当于有这么多个桶),每组包含接近32个数。
上面的解释可能仍不到位,那我们来看具体的函数:
对于set函数,我们可以这样理解,
             arr[i>>SHIFT] |= (1<<(i&MASK))可以转化为
             arr[i/32] = arr[i/32] | (1<<(i%32))
i%32必然处于区间[0, 31],那么1<<(i%32)就是将bit位1向前移动(i%32)位,然后和arr[i/32]相或,因而arr[i/32]的第(i%32)位就为1.
对于test函数,就是上面过程的反过程了。它是用来判断i个这个数是否存在,即arr[i/32]的相应bit位是否为1.
最后,就做排序了,
      for (int i = 0; i < N; i++)
由于[0, N)已经是从小到大排序好的,那么我们只需判断每个数是否存在,若存在,就输出,所以输出结果也就是排序的了。





STL容器的特征:转自:http://lasombra.iteye.com/blog/453852

1. STL有6种序列容器类型 
(1)vector 
它提供对元素的随即访问,在尾部添加和删除元素的时间是固定的,在头部或中部插入和删除元素的复杂度为线性时间。 

(2)deque 
在文件中声明。 
是双端队列,支持随即访问。从deque的开始与末尾位置插入和删除元素的时间是固定的。 
尽管vector和deque都提供对元素的随机访问和在序列中部执行线性时间的插入和删除操作,但vector容器执行这些操作时速度更快一些。 

(3)list 
是双向链表,插入删除元素时间固定。不支持随机访问。与vector不同是,当向容器中插入或删除元素后,链表迭代器指向元素将不变。 
    解释一下:如果一个vector有5个元素,中间插入一个,那么第五个元素包含的值将是以前第四个元素的值,因此,迭代器指向的位置不变,但是数据不同。然而,在链表中插入新元素并不会移动已有的元素,而只是修改链接信息。 指向某个元素的迭代器仍然指向该元素,也就是值相同,链接的位置不同了。 

(4)queue 
在头文件中声明。 queue是一个适配器类,底层类默认为deque。 它不允许随机访问队列元素,甚至不允许遍历队列。可以将元素添加到队尾,查看队尾和队首的元素的值,检查元素数目和测试队列是否为空。 

(5)priority_queue 
与queue的不同是,最大的元素总是在队首,也是一个适配器类,默认的底层类是vector。 
可以修改用于确定哪个元素放在队首的比较方式,方法是提供一个可选的构造函数参数。 

(6)stack 
也是一个适配器类,默认的底层实现为vector。 不允许随机访问堆栈元素,甚至不允许遍历堆栈。可以压入到栈顶,从栈顶弹出元素,查看栈顶元素的值,检查元素数目和测试堆栈是否为空。 

2. STL有4种联合容器:set,multiset, map, multimap; 

联合容器将值与关键字关联在一起,使用关键字来查找值。 
关联容器的长处在于,它提供了对元素的快速访问。 与序列相似,联合容器也允许插入新元素,不过不能指定元素的插入位置。原因是联合容器通常包含用于确定数据存放位置的算法,以便能够很快检索信息。 

(1)set,multiset 
前两种是在set头文件中(以前分别为set.h和multiset.h); 
值的类型与关键字相同。 set删除相同的元素,multiset不会。 
(2)map,multimap 
后两种是在map头文件中(以前分别为map.h和multimap.h)。 
值的类型与关键字不同。 map关键字唯一,multimap关键字不唯一。