位图数据结构的运用
2016-07-29 00:00
357 查看
海量数据排序问题:文件包含1千万条电话号码记录(10**7次方),每条记录都是7位整数,没有重复的整数。要求对文件进行排序,注意大约只有1MB的内存空间可用,有充足的磁盘存储空间可用。请设计一个高效的算法。
(1)运用多趟算法:如果每个号码都使用32位整数来表示,则在1MB存储空间里大约可以存250000个号码。因此,可以使用遍历输入文件40趟的程序来完成排序。在第一趟中,将0至249999之间的任何整数读入内在,对其进行排序后写到输出文件中。第二趟遍历250000至499999之间的整数,依此类推,到第40趟遍历的时候对9750000至9999999之间的整数进行排序。
(2)运用位图数据结构:使用一个具有1000万个位的串(约1.25MB)来表示这个文件,其中当且仅当整数i在文件中存在时,第i位为1。首先将所有的位都置为0,从而将集合初始化为空。然后通过读入文件中的每个整数来建立集合,将每个对应的位都置为1。最后扫描每一位,如果该位为1就输出对应的整数,由此产生有序的输出文件。
(3)排序算法:用C标准库函数qsort,采用的是快速排序。
(4)基于集合的排序算法:用C++ STL中的set容器。
海量数据搜索问题:一个顺序文件包含40亿个随机排列的32位整数,找出一个不在文件中的32位整数。
(1)位图技术:如果有足够的内存,可以使用位图技术。使用536870912个8位字节形成的位图来表示文件的整数。通过扫描位图即可找到缺失的整数。
(2)排序技术:通过对文件进行快速排序,我们能够找到缺失的整数。这时总的运行时间正比于nlogn。
(3)二分搜索技术:如果仅有几百个字节的内存和几个外部的临时顺序文件可用呢?采用二分搜索技术并结合多趟算法。第一遍通过多趟读取40亿个输入整数,并把起始位为0的整数写入一个顺序文件,把起始位为1的整数写入另一个顺序文件。这两个文件中有一个文件最多包含20亿个整数,接下来将该文件用作当前输入并重复探测过程,但这次探测的是第第二个位。如果原始的输入文件包含n元素,那么第一遍将读取n个整数,第二遍最多读取n/2个整数,第三遍最多读取n/4个整数,依此类推,最后我们可以找到缺失的整数。所以总的运行时间正比于n。
关键算法设计思想:位图数据结构、集合数据结构、多趟策略、排序策略、二分搜索策略。
(1)运用多趟算法:如果每个号码都使用32位整数来表示,则在1MB存储空间里大约可以存250000个号码。因此,可以使用遍历输入文件40趟的程序来完成排序。在第一趟中,将0至249999之间的任何整数读入内在,对其进行排序后写到输出文件中。第二趟遍历250000至499999之间的整数,依此类推,到第40趟遍历的时候对9750000至9999999之间的整数进行排序。
(2)运用位图数据结构:使用一个具有1000万个位的串(约1.25MB)来表示这个文件,其中当且仅当整数i在文件中存在时,第i位为1。首先将所有的位都置为0,从而将集合初始化为空。然后通过读入文件中的每个整数来建立集合,将每个对应的位都置为1。最后扫描每一位,如果该位为1就输出对应的整数,由此产生有序的输出文件。
#include <stdio.h> #define BITSPERWORD 32 #define SHIFT 5 #define MASK 0x1F #define N 10000000 int a[1+N/BITSPERWORD]; /* 表示1000万个整数的位向量 */ /* 设置整数i所在的位 */ void set(int i){ /* a中每个元素能表示32个整数,因此表示整数i的位是元素a[i/32]中的某个位, 这个位在a[i/32]的左越第i & 5(i的末五位表示的整数)个位处 */ a[i>>SHIFT] |= (1<<(i & MASK)); } /* 清除整数i所在的位 */ void clr(int i){ a[i>>SHIFT] &= ~(1<<(i & MASK)); } /* 测试位向量中是否有整数i */ int test(int i){ return a[i>>SHIFT] & (1<<(i & MASK)); } int main(void){ int i; for(i=0;i<N;++i) clr(i); while(scanf("%d",&i)!=EOF) //输入要排序的整数 set(i); for(i=0;i<N;++i) if(test(i)) printf("%d/n",i); return 0; }
(3)排序算法:用C标准库函数qsort,采用的是快速排序。
#include <stdio.h> #include <stdlib.h> int intcomp(int *x,int *y){ return *x-*y; } int a[10000000]; int main(void){ int i,n=0; while(scanf("%d",&a )!=EOF) //输入要排序的整数 n++; qsort(a,n,sizeof(int),intcomp); for(i=0;i<n;++i) printf("%d/n",a[i]); return 0; }
(4)基于集合的排序算法:用C++ STL中的set容器。
#include <cstdio> #include <iostream> #include <set> using namespace std; int main(void){ set<int> sint; int i; set<int>::iterator j; while(cin>>i) sint.insert(i); //会进行有序的插入 for(j=sint.begin();j!=sint.end();++j) cout<<*j<<"/n"; return 0; }
海量数据搜索问题:一个顺序文件包含40亿个随机排列的32位整数,找出一个不在文件中的32位整数。
(1)位图技术:如果有足够的内存,可以使用位图技术。使用536870912个8位字节形成的位图来表示文件的整数。通过扫描位图即可找到缺失的整数。
(2)排序技术:通过对文件进行快速排序,我们能够找到缺失的整数。这时总的运行时间正比于nlogn。
(3)二分搜索技术:如果仅有几百个字节的内存和几个外部的临时顺序文件可用呢?采用二分搜索技术并结合多趟算法。第一遍通过多趟读取40亿个输入整数,并把起始位为0的整数写入一个顺序文件,把起始位为1的整数写入另一个顺序文件。这两个文件中有一个文件最多包含20亿个整数,接下来将该文件用作当前输入并重复探测过程,但这次探测的是第第二个位。如果原始的输入文件包含n元素,那么第一遍将读取n个整数,第二遍最多读取n/2个整数,第三遍最多读取n/4个整数,依此类推,最后我们可以找到缺失的整数。所以总的运行时间正比于n。
关键算法设计思想:位图数据结构、集合数据结构、多趟策略、排序策略、二分搜索策略。
相关文章推荐
- 选择问题-输出第k大的数
- 数据结构实验之数组三:快速转置
- [树状数组] poj 3416 Crossing
- 数据结构
- 数据结构的各种树
- 【数据结构与算法】递归
- memset函数使用方法解析
- 数据结构实验之栈四:括号匹配
- 数据结构实验之链表七:单链表中重复元素的删除
- sdut oj2131 数据结构实验之栈一:进制转换
- 数据结构实验之栈二:一般算术表达式转换成后缀式
- 数据结构实验之栈三:后缀式求值
- 一元多项式
- 链表应用3:元素位置互换之移位算法
- 树状数组总结
- 树状数组+离散化——求大范围,大数数组的逆序数
- HashMap数据结构
- 数据结构实验之栈六:下一较大值(二)
- 数据结构实验之串一:KMP简单应用
- 线段树的一点总结