基本方法
1、Hash法
参考:
2、Bit-map法
利用Bit-map方法解决海量数据的查重和去重问题。
/*已知某个文件内包含一些电话号码,每个号码为8位数字,统计不同号码个数*/ #include <iostream> #include <time.h> #include <cstdlib> using namespace std; #define minNumber 10000000 #define maxNumber 99999999 int N = (maxNumber-minNumber+1); //90000000 #define ARRNUMBER 100 //号码数组长度 #define BITS_PER_WORD 32 //一个整型4个字节即32位 #define WORD_OFFSET(b) (b/BITS_PER_WORD) #define BIT_OFFSET(b) (b%BITS_PER_WORD) /*置1*/ void setBit(int *words,int n) { n-=minNumber; words[WORD_OFFSET(n)] |= (1<<BIT_OFFSET(n)); } /*清零*/ void clearBit(int *words,int n) { words[WORD_OFFSET(n)] &= ~(1<<BIT_OFFSET(n)); } int getBit(int *words,int n) { return words[WORD_OFFSET(n)]&(1<<BIT_OFFSET(n)); } int main() { int i,j; int number = 0; int arr[ARRNUMBER]; int *words = new int[1+N/BITS_PER_WORD]; if(words == NULL) { cout<<"new error"<<endl; exit(0); } for(i=0;i<N;i++) { clearBit(words,i); } srand(time(NULL));//设置种子 for(j=0;j<ARRNUMBER;j++) { arr[j]=rand()%N; arr[j]+=minNumber; cout<<arr[j]<<"\t"; } for(j=0;j<ARRNUMBER;j++) { setBit(words,arr[j]); } for(i=0;i<N;i++) { if(getBit(words,i)) { //cout<<i+minNumber<<"\t"; number++; } } cout<<"总个数为:"<<number<<"\n"; delete[] words; words = NULL; return 0; }
使用C++的bitset实现起来更加简单。
3、Bloom filter法
下面是一个简单的Bloom Filter的实现:
参考:
4、数据库优化法
5、倒排索引法
6、外排序法
7、Trie树
Trie树的典型应用是用于统计和排序大量的字符串,经常被搜索引擎系统用于文本词频统计。
下面是一个利用Trie统计某个单词出现的频数的实例。
#include <iostream> #include <cstring> #include <cstdlib> #include <fstream> using namespace std; const int n=26; typedef struct Trie_node { int count; // 统计单词前缀出现的次数 struct Trie_node* next[n]; // 指向各个子树的指针 bool exist; // 标记该结点处是否构成单词 }TrieNode,*Trie; TrieNode *createTrieNode() { TrieNode* node = (TrieNode *)malloc(sizeof(TrieNode)); node->count = 0; node->exist = false; memset(node->next , 0 , sizeof(node->next)); // 初始化为空指针 return node; } void Trie_insert(Trie root, char* word) { Trie node = root; char *p = word; int id; while( *p ) { id = *p - 'a'; if(node->next[id] == NULL) { node->next[id] = createTrieNode(); } node = node->next[id]; // 每插入一步,相当于有一个新串经过,指针向下移动 ++p; //node->count += 1; // 这行代码用于统计每个单词前缀出现的次数(也包括统计每个单词出现的次数) } node->exist = true;// 单词结束的地方标记此处可以构成一个单词 node->count++; } int Trie_search(Trie root, char* word) { Trie node = root; char *p = word; int id; while( *p ) { id = *p - 'a'; node = node->next[id]; ++p; if(node == NULL) { cout<<endl<<word<<"在文件中不存在"; return 0; } } if(node->exist==true) cout<<endl<<word<<"出现了"<<node->count<<"次"; return node->count; } const int num=5000; //产生一个txt文件,模拟字符串 void createStrTXT() { ofstream ofs("word.txt",ios::out); for(int i=0;i<num;++i) { char temp[12]={'\n','\r',rand()%26+97,rand()%26+97,rand()%26+97,rand()%26+97,rand()%26+97,rand()%26+97,rand()%26+97,rand()%26+97,rand()%26+97,'\0'}; char*str=temp; ofs<<str; } ofs.close(); } void establishTrieTree(Trie root) { ifstream ifs("word.txt",ios::in); char str[10]; int i=0; while(ifs>>str) { Trie_insert(root,str); cout<<"插入单词:"<<str<<endl; i++; } cout<<"总共插入"<<i<<"个单词"; ifs.close(); } int main() { //初始化root Trie root=createTrieNode(); createStrTXT(); establishTrieTree( root); Trie_search(root,"zxuglsdsm"); return 0; }
8、堆
堆类型 | 作用 |
---|---|
最大堆 | 求前n小 |
最小堆 | 求前n大 |
双堆 | 中位数 |
参考:词频统计
9、双层桶法
10、MapReduce法
PS:尚未完全整理好,先放出来,慢慢整理。
我的另一个博客www.flyoung.me搜索引擎收录不好,所以那边的文章会同步到博客园上来,现在开始习惯上用markdown写博客了。
作者:像少年啦飞驰
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利.