zoukankan      html  css  js  c++  java
  • 搜索引擎面试题

    搜索引擎会通过日志文件把用户每次检索使用的所有检索串都记录下来,每个查询串的长度为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

    结果如下:

  • 相关阅读:
    [Python] Array Attributes of Numpy lib
    《火球——UML大战需求分析》(第2章 耗尽脑汁的需求分析工作)——2.1 需求分析面面观
    UVA 10201 Adventures in Moving
    《史蒂夫·乔布斯传》官方正式中文版电子书(高清晰完整版)
    为什么要用BitSet
    sed 技巧一例:特定位置插入
    Mac+IPAD上使用wireshark抓包
    【经验谈】XmlSerializer的坑
    HTML语言简单回顾
    不可思议的每日培训(1)——日复一日的每日分享
  • 原文地址:https://www.cnblogs.com/xinyuyuanm/p/2995512.html
Copyright © 2011-2022 走看看