模拟大数据处理、linux下hash_map()使用
来源:互联网 发布:mac win10 iso 下载 编辑:程序博客网 时间:2024/05/16 19:54
写一个程序模拟大数据处理方法。
模拟情景:访问日志里有100万条ip,每条ip占一行。现在要求访问次数最高的前3个ip(后面称作top3)。(假设我们的内存不足以同时处理100万条ip)。
处理方法:逐条处理100万条ip中的每一条ip,根据hash值将ip写入到不同的小文件中(相同hashcode的ip写入同一个小文件中),对每个小文件用hash_map统计每一条ip出现的次数,然后针对每一个小文件求top3(小文件个数设置应使内存足以处理每一个小文件),将每个小文件对应的top3写入对应的统计文件(一个统计文件对应一个小文件)中,最后在所有统计文件中求整体的top3。
求top3时用的方法是:用前三个元素建一个三个元素的小根堆,然后依次遍历剩下的元素,当一个元素出现的次数大于小根堆堆顶元素出现次数时,用这个元素替换堆顶元素,然后对堆顶元素进行一次向下筛选。知道所有元素遍历完,此时的小根堆就是出现次数最多的top3。
我所用的变成环境是:linux,gnu编译器,在此环境下使用hash_map时遇到一个问题:gnu的hash_map不能以std::string类型作为键类型,原因是gnu版编译器没有定义求std::string的hashcode的函数,解决方法是自己定义一个对std::string类型求hashcode的类。gnu版编译器提供的hash_map可以以char*作为键类型,但需要自己定义char*代表的字符串比较类模板(否则hash_map在进行关键字比较时,比较的是指针,而不是字符串),另外,以char*作为键类型时,hash_map是处理的char*变量指向的字符串(hash_map只记住了char*变量,并没有记住字符串),所以为了表示不同的字符串,必须分配空间大量字符串空间已存放不同的字符串(假如用同一个char[]存放每次读取的字符串,虽然每个字符串的hashcode不同,但因为改变了hash表中某一个元素的键的内容(这些键会在iterator++操作时用到:iterator++操作根据当前元素的键算出下一个应该遍历的元素在hash表中的位置,具体做法是:计算当前元素的键的hashcode,根据hashcode就知道这个元素在hash表中的第几个桶中(桶号),找下一个元素时,若当前同的元素已遍历完,那么就需要当前桶号的后面一个桶的号(当前桶号加1),所以若用同一个字符数组存储字符串,做++操作时用来计算hashcode的字符串的内容与插入那个字符串时的内容不同(这样两次计算的hashcode就不相同,也就是查找时计算出来的hashcode不再是当前元素所在的桶的桶号),这就会引起异常结果),使得在进行++操作时差生异常结果,可能导致死循环。),耗费空间较大。
下面分别针对std::string类型作为键类型和char*作为键类型两种情况提供代码。
1、以char*作为键类型
#include<stdio.h>#include<stdlib.h>#include<string.h>#include<iostream>#include<boost/functional/hash.hpp>#include<string>#include<ext/hash_map>using namespace __gnu_cxx;void create_original_file() //生成一个初试大文件{ FILE* original_file_pointer=fopen("./original_file","w"); char str_ip[16]; int rand_number; char str_random[5]; srand(0); for(int i=0;i<1000000;i++) { strcpy(str_ip,"192.168."); rand_number=(int)(255*(rand()/(RAND_MAX+1.0))); sprintf(str_random,"%d",rand_number); strcat(str_ip,str_random); strcat(str_ip,"."); rand_number=(int)(255*(rand()/(RAND_MAX+1.0))); sprintf(str_random,"%d",rand_number); strcat(str_ip,str_random); if(i<999999) fprintf(original_file_pointer,"%s\n",str_ip); else fprintf(original_file_pointer,"%s",str_ip); } fclose(original_file_pointer);}void divide_file() //把初试大文件分割1000个小文件{ boost::hash<std::string> ip_hash; std::size_t ip_hash_code; FILE* small_files[1000]; for(int i=0;i<1000;i++) { char th[30]="./smallfiles/small_file_"; sprintf(th+24,"%d",i); small_files[i]=fopen(th,"w"); } FILE* original_file_pointer=fopen("./original_file","r"); char str_ip[16]; std::string string_ip; for(int i=0;i<1000000;i++) { fscanf(original_file_pointer,"%s",str_ip); string_ip=str_ip; ip_hash_code=ip_hash(string_ip); fprintf(small_files[ip_hash_code%1000],"%s\n",str_ip); } fclose(original_file_pointer); for(int i=0;i<1000;i++) { fclose(small_files[i]); }}struct ip_counter_struct //ip以及其对应的counter的结构体{ std::string struct_string_ip; int struct_counter;};void sift_down(ip_counter_struct struct_map[],int position,int length) //堆的一次向下筛选{ int j=2*position+1; while(j<length) { if(((j+1)<length)&&(struct_map[j+1].struct_counter<struct_map[j].struct_counter)) j=j+1; if(struct_map[position].struct_counter>struct_map[j].struct_counter) { std::swap(struct_map[position],struct_map[j]); position=j; j=2*position+1; } else break; }}void create_heap(ip_counter_struct struct_map[],int length) //建堆{ int i=(length-2)/2; while(i>0) { sift_down(struct_map,i,length); i=(i-1)/2; } sift_down(struct_map,0,length);}struct eqstr //hash_map用来比较char*表示的字符串时所用的类{ bool operator()(const char* s1,const char* s2) const { return strcmp(s1,s2)==0; }};void statistic() //统计每个ip出现的次数,并把每个小文件对应的top3写入对应的统计文件{ ip_counter_struct ip_counter_s[3]; for(int i=0;i<3;i++) { ip_counter_s[i].struct_counter=0; } char str_ip[10000][16]; for(int i=0;i<1000;i++) { hash_map<const char*,int,hash<const char*>,eqstr> ip_counter; char th[30]="./smallfiles/small_file_"; char statistic_th[35]="./statistic/statistic_file_"; sprintf(th+24,"%d",i); sprintf(statistic_th+27,"%d",i); FILE* small_file_pointer=fopen(th,"r"); FILE* statistic_file_pointer=fopen(statistic_th,"w"); int j=0; for(;fscanf(small_file_pointer,"%s",str_ip[j])!=EOF;) { ip_counter[str_ip[j]]=ip_counter[str_ip[j]]+1; j++; } fclose(small_file_pointer); hash_map<const char*,int,hash<const char*>,eqstr>::iterator hash_map_it=ip_counter.begin(); int number; for(number=0;number<3;number++) { if(hash_map_it!=ip_counter.end()) { ip_counter_s[number].struct_string_ip=hash_map_it->first; ip_counter_s[number].struct_counter=hash_map_it->second; ++hash_map_it; } else break; } switch(number) { case 0: break; case 1: fprintf(statistic_file_pointer,"%s ",ip_counter_s[0].struct_string_ip.c_str()); fprintf(statistic_file_pointer,"%d",ip_counter_s[0].struct_counter); break; case 2: fprintf(statistic_file_pointer,"%s ",ip_counter_s[0].struct_string_ip.c_str()); fprintf(statistic_file_pointer,"%d\n",ip_counter_s[0].struct_counter); fprintf(statistic_file_pointer,"%s ",ip_counter_s[1].struct_string_ip.c_str()); fprintf(statistic_file_pointer,"%d\n",ip_counter_s[1].struct_counter); break; case 3: create_heap(ip_counter_s,3); while(hash_map_it!=ip_counter.end()) { if(hash_map_it->second>ip_counter_s[0].struct_counter) { ip_counter_s[0].struct_string_ip=hash_map_it->first; ip_counter_s[0].struct_counter=hash_map_it->second; sift_down(ip_counter_s,0,3); } ++hash_map_it; } for(int i=0;i<3;i++) { fprintf(statistic_file_pointer,"%s ",ip_counter_s[i].struct_string_ip.c_str()); fprintf(statistic_file_pointer,"%d\n",ip_counter_s[i].struct_counter); } break; defualt:break; } fclose(statistic_file_pointer); }}void get_total_top_k() //得到整体的top3{ ip_counter_struct ip_counter_s[3]; for(int i=0;i<3;i++) { ip_counter_s[i].struct_counter=0; } int number=0; char str_ip[16]=""; int counter=0; for(int i=0;i<1000;i++) { char statistic_th[35]="./statistic/statistic_file_"; sprintf(statistic_th+27,"%d",i); FILE* statistic_file_pointer=fopen(statistic_th,"r"); while(fscanf(statistic_file_pointer,"%s",str_ip)!=EOF) { fscanf(statistic_file_pointer,"%d",&counter); if(number<2) { ip_counter_s[number].struct_string_ip=str_ip; ip_counter_s[number].struct_counter=counter; number++; } else if(number==2) { ip_counter_s[number].struct_string_ip=str_ip; ip_counter_s[number].struct_counter=counter; number++; create_heap(ip_counter_s,3); } else { if(counter>ip_counter_s[0].struct_counter) { ip_counter_s[0].struct_string_ip=str_ip; ip_counter_s[0].struct_counter=counter; sift_down(ip_counter_s,0,3); } number++; } } fclose(statistic_file_pointer); } for(int i=0;i<3;i++) std::cout<<ip_counter_s[i].struct_string_ip<<" "<<ip_counter_s[i].struct_counter<<std::endl;}int main(){ create_original_file(); divide_file(); statistic(); get_total_top_k(); return 0;}
2、std::string作为键类型
#include<stdio.h>#include<stdlib.h>#include<string.h>#include<iostream>#include<boost/functional/hash.hpp>#include<string>#include<ext/hash_map>using namespace __gnu_cxx;namespace __gnu_cxx{ template<> struct hash<std::string> //定义计算std::string的hashcode的类 { std::size_t operator()(const std::string &s) const { boost::hash<std::string> string_hash; return string_hash(s); } };}void create_original_file(){ FILE* original_file_pointer=fopen("./original_file","w"); char str_ip[16]; int rand_number; char str_random[5]; srand(0); for(int i=0;i<1000000;i++) { strcpy(str_ip,"192.168."); rand_number=(int)(255*(rand()/(RAND_MAX+1.0))); sprintf(str_random,"%d",rand_number); strcat(str_ip,str_random); strcat(str_ip,"."); rand_number=(int)(255*(rand()/(RAND_MAX+1.0))); sprintf(str_random,"%d",rand_number); strcat(str_ip,str_random); if(i<999999) fprintf(original_file_pointer,"%s\n",str_ip); else fprintf(original_file_pointer,"%s",str_ip); } fclose(original_file_pointer);}void divide_file(){ boost::hash<std::string> ip_hash; std::size_t ip_hash_code; FILE* small_files[1000]; for(int i=0;i<1000;i++) { char th[30]="./smallfiles/small_file_"; sprintf(th+24,"%d",i); small_files[i]=fopen(th,"w"); } FILE* original_file_pointer=fopen("./original_file","r"); char str_ip[16]; std::string string_ip; for(int i=0;i<1000000;i++) { fscanf(original_file_pointer,"%s",str_ip); string_ip=str_ip; ip_hash_code=ip_hash(string_ip); fprintf(small_files[ip_hash_code%1000],"%s\n",str_ip); } fclose(original_file_pointer); for(int i=0;i<1000;i++) { fclose(small_files[i]); }}struct ip_counter_struct{ std::string struct_string_ip; int struct_counter;};void sift_down(ip_counter_struct struct_map[],int position,int length){ int j=2*position+1; while(j<length) { if(((j+1)<length)&&(struct_map[j+1].struct_counter<struct_map[j].struct_counter)) j=j+1; if(struct_map[position].struct_counter>struct_map[j].struct_counter) { std::swap(struct_map[position],struct_map[j]); position=j; j=2*position+1; } else break; }}void create_heap(ip_counter_struct struct_map[],int length){ int i=(length-2)/2; while(i>0) { sift_down(struct_map,i,length); i=(i-1)/2; } sift_down(struct_map,0,length);}void statistic(){ ip_counter_struct ip_counter_s[3]; for(int i=0;i<3;i++) { ip_counter_s[i].struct_counter=0; } char str_ip[16]=""; std::string string_ip; for(int i=0;i<1000;i++) { hash_map<std::string,int> ip_counter; char th[30]="./smallfiles/small_file_"; char statistic_th[35]="./statistic/statistic_file_"; sprintf(th+24,"%d",i); sprintf(statistic_th+27,"%d",i); FILE* small_file_pointer=fopen(th,"r"); FILE* statistic_file_pointer=fopen(statistic_th,"w"); for(;fscanf(small_file_pointer,"%s",str_ip)!=EOF;) { string_ip=str_ip; ip_counter[string_ip]=ip_counter[string_ip]+1; } fclose(small_file_pointer); hash_map<std::string,int>::iterator hash_map_it=ip_counter.begin(); int number; for(number=0;number<3;number++) { if(hash_map_it!=ip_counter.end()) { ip_counter_s[number].struct_string_ip=hash_map_it->first; ip_counter_s[number].struct_counter=hash_map_it->second; ++hash_map_it; } else break; } switch(number) { case 0: break; case 1: fprintf(statistic_file_pointer,"%s ",ip_counter_s[0].struct_string_ip.c_str()); fprintf(statistic_file_pointer,"%d",ip_counter_s[0].struct_counter); break; case 2: fprintf(statistic_file_pointer,"%s ",ip_counter_s[0].struct_string_ip.c_str()); fprintf(statistic_file_pointer,"%d\n",ip_counter_s[0].struct_counter); fprintf(statistic_file_pointer,"%s ",ip_counter_s[1].struct_string_ip.c_str()); fprintf(statistic_file_pointer,"%d\n",ip_counter_s[1].struct_counter); break; case 3: create_heap(ip_counter_s,3); while(hash_map_it!=ip_counter.end()) { if(hash_map_it->second>ip_counter_s[0].struct_counter) { ip_counter_s[0].struct_string_ip=hash_map_it->first; ip_counter_s[0].struct_counter=hash_map_it->second; sift_down(ip_counter_s,0,3); } ++hash_map_it; } for(int i=0;i<3;i++) { fprintf(statistic_file_pointer,"%s ",ip_counter_s[i].struct_string_ip.c_str()); fprintf(statistic_file_pointer,"%d\n",ip_counter_s[i].struct_counter); } break; defualt:break; } fclose(statistic_file_pointer); }}void get_total_top_k(){ ip_counter_struct ip_counter_s[3]; for(int i=0;i<3;i++) { ip_counter_s[i].struct_counter=0; } int number=0; char str_ip[16]=""; int counter=0; for(int i=0;i<1000;i++) { char statistic_th[35]="./statistic/statistic_file_"; sprintf(statistic_th+27,"%d",i); FILE* statistic_file_pointer=fopen(statistic_th,"r"); while(fscanf(statistic_file_pointer,"%s",str_ip)!=EOF) { fscanf(statistic_file_pointer,"%d",&counter); if(number<2) { ip_counter_s[number].struct_string_ip=str_ip; ip_counter_s[number].struct_counter=counter; number++; } else if(number==2) { ip_counter_s[number].struct_string_ip=str_ip; ip_counter_s[number].struct_counter=counter; number++; create_heap(ip_counter_s,3); } else { if(counter>ip_counter_s[0].struct_counter) { ip_counter_s[0].struct_string_ip=str_ip; ip_counter_s[0].struct_counter=counter; sift_down(ip_counter_s,0,3); } number++; } } fclose(statistic_file_pointer); } for(int i=0;i<3;i++) std::cout<<ip_counter_s[i].struct_string_ip<<" "<<ip_counter_s[i].struct_counter<<std::endl;}int main(){ create_original_file(); divide_file(); statistic(); get_total_top_k(); return 0;}
- 模拟大数据处理、linux下hash_map()使用
- Linux 下hash_map的使用
- Linux下hash_map的使用
- Linux 下hash_map的使用
- linux下使用hash_map及STL总结
- Linux下hash_map之类
- linux hash_map使用
- linux hash_map的使用
- linux hash_map的使用(g++)
- 模拟大数据处理之——bitset
- linux c++ stl hash_map basic_string 使用
- linux hash_map
- hash_map 使用
- Linux下分布式海量数据处理
- linux下使用系统调用模拟SHELL
- linux下使用mdadm模拟阵列--模拟虚拟磁盘
- Linux大数据处理踩坑实录
- 在windows 和 linux下引入hash_set、hash_map头文件
- BNU29375:Two Strings
- hdu 4544 湫湫系列故事——消灭兔子, 贪心算法+小顶堆
- Java知识点复习2 与运行环境交互
- “菲特”面临四个方面的不利因素
- HDOJ 4324 —— 拓扑排序 || DFS时间戳 || 竞赛图
- 模拟大数据处理、linux下hash_map()使用
- java常用代码一(粘贴即用)---目录
- Android的Intent的Action大全
- Socket编程:基础部分
- hdu 1008 Dogs 广度优先搜索
- 【数据结构】链表
- iOS中对表格数据的修改
- java泛型小问题
- JavaScript的异步实现