搜索引擎面试题

搜索引擎会通过日志文件把用户每次检索使用的所有检索串都记录下来,每个查询串的长度为1-255字节。假设目前一个日志文件中有一千万个记录(这些查询串的重复度比较高,虽然总数是1千万,但如果除去重复后,不超过3百万个。一个查询串的重复度越高,说明查询它的用户越多,也就是越热门),请你统计最热门的10个查询串,要求使用的内存不能超过1G。

1000万条记录,每条记录最大为255Byte,那么日志文件最大有2.5G左右,大于1G内存。但是题目中又提到这样的1000万条记录中有许多是重复的,出去重复的话只有300万条记录,存储这样的300万条记录需要0.75G左右的内存,小于1G内存。那么我们可以考虑将这些无重复的记录装入内存,这是我们需要一种数据结构,这种数据结构即能够存储查询串,又能存储查询串的出现次数,我们可以通过hashmap<query,count>来保存。读取文件,创建一个hashmap,如果hashmap中存储了遍历到的query,则修改该query所对应的count值,使其+1;如果hashmap中没有这个query,那么往haspmap中插入<query,1>。这样我们就创建好了一个包含所有query和次数的hashmap。

然后我们创建一个长度为10最大堆MaxHeap,遍历hashmap,如果MaxHeap未满,那么往MaxHeap中插入这个键值对,如果MinHeap满了,则比较遍历到的元素的count值堆顶的count,如果遍历到元素的count大于堆顶count值,删除堆顶元素,插入当前遍历到的元素。

遍历完整个hashmap以后,在MaxHeap中存储的就是最热门10个查询串。

下面是根据上面思路自己编写的代码。

 

#include <iostream>
#include <string>   
#include <malloc.h>   
#include <stdlib.h>   
#include <fstream>  
using namespace std;

#define N	10

struct _linkList
{
	char* strValue;
	int cnt;
	_linkList* next;
};

class CHash
{
public:
	_linkList* list[350];
	CHash();
	~CHash();
	int HashFunc(char src[]);
	void InitHash();
};

CHash::CHash()
{
	int i;
	for (i = 0; i < 350; i++)
	{
		list[i] = (_linkList* )malloc(sizeof(_linkList));
		list[i]->strValue = NULL;
		list[i]->cnt = 0;
		list[i]->next = NULL;
	}
}

CHash::~CHash()
{
	int i;
	for (i = 0; i < 350; i++)
	{
		free(list[i]);
	}
}

int CHash::HashFunc(char src[])
{
	char* p = src;
	int sum = 0;
	while (*p != '\0')
	{
		int mod = (int)(*p) % 90;
		if (mod % 2 ==0)
		{
			mod *= 2;
		}
		sum+=mod;
		p++;
	}
	return sum;
}

void CHash::InitHash()
{
	ifstream fin;
	char str[10];
	fin.open("data1.txt");
	while (fin>>str)
	{
		int addr = HashFunc(str);
		_linkList* head = list[addr];
		bool isRight = false;

		while (head->next != NULL)
		{
			head=head->next;
			if (strcmp(head->strValue, str) == 0)
			{
				isRight = true;
				head->cnt++;
				break;
			}
		}

		if (!isRight)
		{
			_linkList* newNode=(_linkList*)malloc(sizeof(_linkList));
			newNode->strValue = new char[10];
			newNode->cnt=1;
			newNode->next = NULL;
			strcpy(newNode->strValue, str);
			head->next = newNode;
		}
	}
}

void swap(_linkList* l, int s, int m)
{
	int temp;
	char str[10];
	temp = l[s].cnt;
	strcpy(str,l[s].strValue);

	l[s].cnt = l[m].cnt;
	strcpy(l[s].strValue, l[m].strValue);

	l[m].cnt=temp;
	strcpy(l[m].strValue, str);
}

void swap(_linkList* l, int s, _linkList* m)
{
	int temp;
	char str[10];
	temp = l[s].cnt;
	strcpy(str,l[s].strValue);

	l[s].cnt = m->cnt;
	strcpy(l[s].strValue, m->strValue);

	m->cnt=temp;
	strcpy(m->strValue, str);
}

void heapAdjust(_linkList* l, int s, int m)
{
	int temp = l[s].cnt;
	char str[10];
	strcpy(str,l[s].strValue);
	for (int j = 2*s; j <= m; j *= 2)
	{
		if (j<m && l[j].cnt < l[j+1].cnt)
			++j;
		if (temp >= l[j].cnt)
			break;
		l[s].cnt = l[j].cnt;
	//	l[s].strValue = l[j].strValue;
		strcpy(l[s].strValue,l[j].strValue);
		//strcpy(str, l[j].strValue);
		s=j;
	}
	l[s].cnt = temp;
	//l[s].strValue = str;
	strcpy(l[s].strValue, str);
}

void heapSort(_linkList* l)
{
/*
	for (int ii = 1; ii <= N; ii++)
	{
		cout<<l[ii].cnt<<" "<<l[ii].strValue<<endl;
	}
	*/
	int i;
	for (i = N/2; i > 0; i--)
	{
		heapAdjust(l, i, N);
	}

	for (i = N; i > 1; i--)
	{
		swap(l,i,1);
		heapAdjust(l, 1, i-1);
	}
}

int main()
{
	CHash CH;
	CH.InitHash();
	_linkList Max[N+1];
	Max[0].cnt = 0;
	Max[0].strValue = NULL;
	_linkList* head;
	int initCount = 1;
	int i = 0;
	while (initCount <= N && i < 350)
	{
		head=CH.list[i];
		while (head->next && initCount <= N)
		{
			head=head->next;
			Max[initCount].cnt = head->cnt;
			Max[initCount].strValue = new char[10];
			Max[initCount].next = NULL;
			strcpy(Max[initCount].strValue,head->strValue);
			initCount++;
		}
		i++;
	}
/*
	for (int i = 1; i <= N; i++)
	{
		cout<<Max[i].cnt<<" "<<Max[i].strValue<<endl;
	}
	***/
	heapSort(Max);
	/***
	cout<<"after sort...."<<endl;
	for (int i = 1; i <= N; i++)
	{
		cout<<Max[i].cnt<<" "<<Max[i].strValue<<endl;
	}*/

	while (i < 350)
	{
		while (head->next && i < 350)
		{
			head=head->next;
			if (head->cnt > Max[1].cnt)
			{
				swap(Max, 1, head);
				heapSort(Max);
			}
		}
		i++;
		head=CH.list[i];
	}
	for (int i = 1; i <= N; i++)
	{
		cout<<Max[i].cnt<<" "<<Max[i].strValue<<endl;
	}	
}

 


数据data1.txt如下:

 

baidu
baidu
baidu
baidu
baidu
baidu
baidu
baidu
baidu
baidu
baidu
baidu
baidu
baidu
baidu
baidu
google
google
google
google
google
google
google
google
google
google
google
google
qq
qq
qq
qq
qq
qq
qq
qq
qq
qq
qq
qq
aa
aa
aa
aa
aa
aa
aa
bb
bb
bb
bb
cc
cc
bb
bb
bb
cc
cc
aa
bb
cc
163
163
163
hh
hh
vs
vs
vs
vs
vs
vs
hello
hello
hello
hello
what
what
what
what
what
what
how
how

结果如下:

 

 

转载于:https://www.cnblogs.com/xinyuyuanm/archive/2013/04/02/2995512.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值