搜尋引擎面試題

weixin_33941350發表於2013-04-02
搜尋引擎會通過日誌檔案把使用者每次檢索使用的所有檢索串都記錄下來,每個查詢串的長度為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

結果如下:

 

 

相關文章