/*
搜索引擎会通过日志文件把用户每次检索使用的所有检索串都记录下来,每个查询串的长度为1-255字节。
假设目前一个日志文件中有一千万个记录(这些查询串的重复度比较高,虽然总数是1千万,但如果除去
重复后,不超过3百万个。一个查询串的重复度越高,说明查询它的用户越多,也就是越热门),请你统计
最热门的10个查询串,要求使用的内存不能超过1G。
edit by colin
2014-11-02
*/
#include <iostream>
#include <fstream>
#include <cstdlib>
#include <cmath>
#include <ctime>
// 由于自己电脑没有hash_map,就直接用的map,红黑树搜索,接近二分log3000000 ~ 20
// 考虑到hash无冲突的情况下才有O(1),最坏情况是O(n),平均而言可能会好一些。
#include <map>
#include <string>
#include <algorithm>
//#inlcude <ext/hash_map>
using namespace std;
char *mypath = "d:/tempdata/out.txt";
struct mHeap{
int n;
string ss;
}myData[10];
// 比较函数
int leftchild(int i)
{
return 2*i+1;
}
void mkheap(int i,int n)
{
int nchild;
mHeap tmp;
for(tmp = myData[i];leftchild(i)<n;i=nchild)
{
nchild = leftchild(i);
if ((nchild != n - 1) && (myData[nchild + 1].n < myData[nchild].n))
++nchild;
if (tmp.n > myData[nchild].n){
myData[i].n = myData[nchild].n;
myData[i].ss = myData[nchild].ss;
}
else
break;
}
myData[i].n = tmp.n;
myData[i].ss = tmp.ss;
}
void addElement(int n,string s,int *c)
{
int v = 0;
if(*c < 10){
myData[*c].n = n;
myData[*c].ss = s;
v = 1;
++*c;
}else{
if(myData[0].n < n){
myData[0].n = n;
myData[0].ss = s;
v = 2;
}
}
if(v==1 && *c == 10){
for(int i=4;i>=0;--i)
mkheap(i,10);
}else if(v==2 && *c == 10){
mkheap(0,10);
}
}
int myrandom(int min,int max)
{
double x = (double)rand()/RAND_MAX;
return min + floor((max-min)*x);
}
// 生产随机数据写入到文本
void generatequery(int m)
{
srand((unsigned)(time(NULL)));
ofstream out(mypath,ios::binary|ios::out);
char tmp[256];
char *mychar;
int i;
for(int j=0;j<m;++j){
int n = myrandom(2,255);
for(i=0;i<n;++i)
tmp[i] = (char)myrandom(0,25)+'A';
tmp[i] = '\0';
mychar = tmp;
out.write(mychar,sizeof(char)*255);
}
}
int main()
{
// generate 300W 个字符串
// generatequery(3000000);
int count = 0;
map<string, int> mydata;
char tmp[256];
ifstream in(mypath,ios::binary|ios::in);
// 出现过就计数,未出现过加入
while(in.read(tmp,sizeof(char)*255)){
string str;
str = tmp;
if(mydata.find(str) != mydata.end())
mydata[str]++;
else
mydata.insert(map<string,int>::value_type (str,1));
}
// 对文件进行遍历操作
for(map<string, int>::iterator iter = mydata.begin();iter != mydata.end(); ++iter)
{
addElement(iter->second,iter->first,&count);
}
// 输出小堆
for(int i =0;i<10;++i)
{
cout<<myData[i].ss<<" "<<myData[i].n<<endl;
}
return 0;
}
大数据-1000W 条query,大概有300W不重复,计算出前十热度索引
最新推荐文章于 2024-09-22 14:48:38 发布