海量数据处理实例--几个使用bit-map的简单例子
2013-10-21 21:49
441 查看
这个例子是很简单的使用了bit-map的思想,但是其中的想法还是没有这里的例子优秀,代码如下:
下面介绍一个使用的例子,早一百万的数据中使用bit-map:
产生一百万数据的代码:
使用bit_set 进行排序:
位图排序的实现示例:
归并排序方式实现:
还有一种是桶排序方式实现的:
#include <stdio.h> #include <memory.h> #define BYTESIZE 8 void SetBit(char *p, int posi) { int i=0; for(; i<(posi/BYTESIZE); i++) { p++; } *p = *p|(0x01<<(posi%BYTESIZE));//将该Bit位赋值1 return; } void BitMapSortDemo() { //为了简单起见,我们不考虑负数 int num[] = {3,5,2,10,6,12,8,14,9}; int i=0,j=0; //BufferLen这个值是根据待排序的数据中最大值确定的 //待排序中的最大值是14,因此只需要2个Bytes(16个Bit) //就可以了。 int BufferLen = 2; char *pBuffer = (char*)malloc(sizeof(char)*2); //要将所有的Bit位置为0,否则结果不可预知。 memset(pBuffer,0,BufferLen); for(;i<9;i++) { //首先将相应Bit位上置为1 SetBit(pBuffer,num[i]); } //输出排序结果 for(i=0;i<BufferLen;i++)//每次处理一个字节(Byte) { for(j=0;j<BYTESIZE;j++)//处理该字节中的每个Bit位 { //判断该位上是否是1,进行输出,这里的判断比较笨。 //首先得到该第j位的掩码(0x01<<j),将内存区中的 //位和此掩码作与操作。最后判断掩码是否和处理后的 //结果相同 if((*pBuffer&(0x01<<j)) == (0x01<<j)) { printf("%d ",i*BYTESIZE + j); } } pBuffer++; } } int main() { BitMapSortDemo(); return 0; }
下面介绍一个使用的例子,早一百万的数据中使用bit-map:
产生一百万数据的代码:
#include <iostream> #include <time.h> #include <assert.h> #include <stdio.h> #include <stdlib.h> using namespace std; const int size = 10000000; int num[size]; int main() { int n; FILE *fp = fopen("data.txt", "w"); assert(fp); for (n = 1; n <= size; n++) //之前此处写成了n=0;n<size。导致下面有一段小程序的测试数据出现了0,特此订正。 num = n; srand((unsigned)time(NULL)); int i, j; for (n = 0; n < size; n++) { i = (rand() * RAND_MAX + rand()) % 10000000; j = (rand() * RAND_MAX + rand()) % 10000000; swap(num[i], num[j]); } for (n = 0; n < size; n++) fprintf(fp, "%d ", num ); fclose(fp); return 0; }
使用bit_set 进行排序:
//位图方式解决海量数据排序,数据不能有重复 //使用 C++ stl的 bitset #include <iostream> #include <bitset> #include <assert.h> #include <time.h> #include <stdio.h> #include <stdlib.h> using namespace std; const int max_each_scan = 5000000; int main() { clock_t begin = clock(); bitset<max_each_scan> bit_map; bit_map.reset(); // open the file with the unsorted data FILE *fp_unsort_file = fopen("data.txt", "r"); assert(fp_unsort_file); int num; // the first time scan to sort the data between 0 - 4999999 while (fscanf(fp_unsort_file, "%d ", &num) != EOF) { if (num < max_each_scan) //有这个数字,将bit_map的对应的位设置为1 bit_map.set(num, 1); } FILE *fp_sort_file = fopen("sort.txt", "w"); assert(fp_sort_file); int i; // write the sorted data into file for (i = 0; i < max_each_scan; i++) { if (bit_map[i] == 1) fprintf(fp_sort_file, "%d ", i); } // the second time scan to sort the data between 5000000 - 9999999 int result = fseek(fp_unsort_file, 0, SEEK_SET); if (result) cout << "fseek failed!" << endl; else { bit_map.reset(); while (fscanf(fp_unsort_file, "%d ", &num) != EOF) { if (num >= max_each_scan && num < 10000000) { num -= max_each_scan; bit_map.set(num, 1); } } for (i = 0; i < max_each_scan; i++) { if (bit_map[i] == 1) fprintf(fp_sort_file, "%d ", i + max_each_scan); } } clock_t end = clock(); cout<<"用位图的方法,耗时:"<<endl; cout << (end - begin) / CLK_TCK << "s" << endl; fclose(fp_sort_file); fclose(fp_unsort_file); return 0; }
位图排序的实现示例:
#include <iostream> #include <memory.h> #define BYTESIZE 8 using namespace std; void setBit(char *p,int posi) { for(int i = 0;i < (posi/BYTESIZE);i ++) { p ++; } *p = *p|(0x01 << (posi%BYTESIZE));//将该Bit位赋值1 return; } int main() { int num[] = {3,2,5,7,12,24,9,8,6}; const int BufferLen = 2; char *pBuffer = new char[BufferLen]; memset(pBuffer,0,BufferLen); for(int i = 0;i < 9;i ++) setBit(pBuffer,num[i]); //输出排序结果 for(int i = 0;i < BufferLen;i ++)//每次处理一个字节 { for(int j = 0;j < BYTESIZE;j ++) { if( (*pBuffer&(0x01<<j)) == (0x01<<j)) cout << i * BYTESIZE + j << " "; } pBuffer ++; } return 0; }
归并排序方式实现:
//copyright@ 纯净的天空 && yansha //5、July,updated,2010.05.28。 #include <iostream> #include <ctime> #include <fstream> #include <stdio.h> #include <stdlib.h> #include <string.h> //#include "ExternSort.h" using namespace std; //使用多路归并进行外排序的类 //ExternSort.h /** 大数据量的排序 * 多路归并排序 * 以千万级整数从小到大排序为例 * 一个比较简单的例子,没有建立内存缓冲区*/ #ifndef EXTERN_SORT_H #define EXTERN_SORT_H #include <cassert> class ExternSort { public:void sort() { time_t start = time(NULL); //将文件内容分块在内存中排序,并分别写入临时文件 int file_count = memory_sort(); //归并临时文件内容到输出文件 merge_sort(file_count); time_t end = time(NULL); printf("total time:%f/n", (end - start) * 1000.0/ CLOCKS_PER_SEC); } //input_file:输入文件名 //out_file:输出文件名 //count: 每次在内存中排序的整数个数 ExternSort(const char *input_file, const char * out_file, int count) { m_count = count; m_in_file = new char[strlen(input_file) + 1]; strcpy(m_in_file, input_file); m_out_file = new char[strlen(out_file) + 1]; strcpy(m_out_file, out_file); } virtual ~ExternSort() { delete [] m_in_file; delete [] m_out_file; } private:int m_count; //数组长度 char *m_in_file; //输入文件的路径 char *m_out_file; //输出文件的路径 protected:int read_data(FILE* f, int a[], int n) { int i = 0; while(i < n && (fscanf(f, "%d", &a[i]) != EOF)) i++; printf("read:%d integer/n", i); return i; } void write_data(FILE* f, int a[], int n) { for(int i = 0; i < n; ++i) fprintf(f, "%d ", a[i]); } char* temp_filename(int index) { char *tempfile = new char[100]; sprintf(tempfile, "temp%d.txt", index); return tempfile; } static int cmp_int(const void *a, const void *b) { return *(int*)a - *(int*)b; } int memory_sort() { FILE* fin = fopen(m_in_file, "rt"); int n = 0, file_count = 0; int *array = new int[m_count]; //每读入m_count个整数就在内存中做一次排序,并写入临时文件 while(( n = read_data(fin, array, m_count)) > 0) { qsort(array, n, sizeof(int), cmp_int); //这里,调用了库函数阿,在第四节的c实现里,不再调用qsort。 char *fileName = temp_filename(file_count++); FILE *tempFile = fopen(fileName, "w"); free(fileName); write_data(tempFile, array, n); fclose(tempFile); } delete [] array; fclose(fin); return file_count; } void merge_sort(int file_count) { if(file_count <= 0) return; //归并临时文件 FILE *fout = fopen(m_out_file, "wt"); FILE* *farray = new FILE*[file_count]; int i; for(i = 0; i < file_count; ++i) { char* fileName = temp_filename(i); farray[i] = fopen(fileName, "rt"); free(fileName); } int *data = new int[file_count]; //存储每个文件当前的一个数字 bool *hasNext = new bool[file_count]; //标记文件是否读完 memset(data, 0, sizeof(int) * file_count); memset(hasNext, 1, sizeof(bool) * file_count); for(i = 0; i < file_count; ++i) { if(fscanf(farray[i], "%d", &data[i]) == EOF) //读每个文件的第一个数到data数组 hasNext[i] = false; } while(true) { //求data中可用的最小的数字,并记录对应文件的索引 int min = data[0]; int j = 0; while (j < file_count && !hasNext[j]) j++; if (j >= file_count) //没有可取的数字,终止归并 break; for(i = j + 1; i < file_count; ++i) { if(hasNext[i] && min > data[i]) { min = data[i];j = i; } } if(fscanf(farray[j], "%d", &data[j]) == EOF) //读取文件的下一个元素 hasNext[j] = false; fprintf(fout, "%d ", min); } delete [] hasNext; delete [] data; for(i = 0; i < file_count; ++i) { fclose(farray[i]); } delete [] farray; fclose(fout); } }; #endif //测试主函数文件 /** 大文件排序* 数据不能一次性全部装入内存* 排序文件里有多个整数, 整数之间用空格隔开*/ const unsigned int count = 10000000; // 文件里数据的行数 const unsigned int number_to_sort = 1000000; //在内存中一次排序的数量 const char *unsort_file = "data.txt"; //原始未排序的文件名 const char *sort_file = "sort_data.txt"; //已排序的文件名 void init_data(unsigned int num); //随机生成数据文件 int main(int argc, char* *argv) { srand(time(NULL)); init_data(count); ExternSort extSort(unsort_file, sort_file, number_to_sort); extSort.sort(); return 0; } void init_data(unsigned int num) { FILE* f = fopen(unsort_file, "wt"); for(int i = 0; i < num; ++i) fprintf(f, "%d ", rand()); fclose(f); }
还有一种是桶排序方式实现的:
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <iostream> #include <ctime> #define LOW 18 //桶大小 #define FILE_NUM 39 //桶对应的文件数 #define MEM_SIZE 256*1024 using namespace::std; int memory[MEM_SIZE]; //1M //对ifp中的数据进行排序,结果输出到ofp中 ,i是正在处理的桶的编号 void sort(FILE*ifp, FILE *ofp, int i) { memset(memory,0,1024*1024); int d; int high=i<<LOW; //保存数据的高位 if(fscanf(ifp, "%d", &d)==1) { ++memory[d&0x3ffff]; //计数,只是用低18位 high=d&0xfffc0000; //保存高位 } while(fscanf(ifp, "%d", &d)==1) { ++memory[d&0x3ffff]; //计数,不考虑高五位 } for (int i=0; i<MEM_SIZE; ++i) { int num=memory[i]; while(num--) { fprintf(ofp,"%d ",i|high); //输出结果 } } } int main() { FILE *fp_tmp[FILE_NUM]; FILE *fp_data; if(NULL==(fp_data=fopen("data.txt","r"))) //打开测试数据 exit(0); int d; int i; time_t start = time(NULL); //开始计时 for (i=0; i<FILE_NUM; ++i) //创建桶对应的FILE_NUM个文件 { char buf[64]="tmp_"; char buf_int[4]; itoa(i, buf_int, 10); strcat(buf,buf_int); strcat(buf,".txt"); if((fp_tmp[i]=fopen(buf,"w+"))==NULL) exit(0); } while(fscanf(fp_data,"%d",&d)==1) //读入数据存放到各个桶中 { int i = d >> LOW; //不管这个数多大,右移18位啊,都变成0了 fprintf(fp_tmp[d >> LOW], "%d ",d&0x3ffff); } for (i=0; i<FILE_NUM; ++i) //初始化文件指针 { rewind(fp_tmp[i]); } FILE * out_fp; if(NULL==(out_fp=fopen("out.txt","w"))) //out.txt用于保存排序后的数据 exit(0); for (i=0; i<FILE_NUM; ++i) { sort(fp_tmp[i],out_fp,i); //分别对每个桶进行排序 } for (i=0; i<FILE_NUM; ++i) //关闭文件 { fclose(fp_tmp[i]); } time_t end = time(NULL); //停止计时 printf("total time:%f/n", (end - start) * 1000.0/ CLOCKS_PER_SEC); return 0; }
相关文章推荐
- 简单处理海量数据:STL的hasp_map使用+堆排序
- 海量数据处理--bit-map的使用
- 十七道海量数据处理面试题与Bit-map详解
- 海量数据处理算法—Bit-Map
- jdbc的简单封装(使用map处理结果集)
- 十七道海量数据处理面试题与Bit-map详解---之我对bitmap的理解
- 十七道海量数据处理面试题与Bit-map详解
- 海量数据处理 ——Bit-map
- 使用事件处理创建一个简单的绘图实例程序 python
- 海量数据处理专题(四)——Bit-map
- 海量数据处理算法—Bit-Map
- 海量数据处理面试题集锦与Bit-map详解
- 十七道海量数据处理面试题与Bit-map详解
- 海量数据处理专题(四)——Bit-map
- 海量数据处理问题之Bit-Map详解
- 海量数据处理面试题集锦与Bit-map详解
- 海量数据处理方法--十七道海量数据处理面试题与Bit-map详解(转)
- 海量数据处理算法—Bit-Map
- objc_runtime使用方法的几个简单例子
- 海量数据处理专题(四)——Bit-map