一道面试题,内存受限的情况,如何在海量的数据中找到重复最多的

面对内存500K限制和百万条20B数据的查询问题,如何寻找重复最多的一条记录?通过使用哈希算法将大文件分割成多块,并保证相同记录尽可能在同一文件,然后对每个文件排序,最后使用堆进行总归并,解决此问题。文章介绍了实现方法和代码示例。
摘要由CSDN通过智能技术生成

昨天,去面试,被问到一题,给你内存500K,一百万条查询数据,每条数据20B,如何寻找到最多的那一条,内存不受限制的话,可以使用hash,之后排序就搞定了,但是内存受限的话,还真没有想过这个问题,因此憋了十分钟左右,还是没有想到,最后放弃了。之后的面试。。。。。。哎,果断的跪了。
回到实验室后的第一件事情,叹气之余,最大的想法就是我要把这个给编写出来,不然还是提高不了自己。
首先说说思路,内存受到限制,一百万条记录不可能放到内存中的,因此必须要把这个大文件(后文称记录文件)想办法分割成多块,每块保持在内存上限之下,要充分的运用硬盘资源,不过这样速度肯定慢下来了。分割多块的方法也不少,从记录文件中先读到差不多的数量就新建一个文件写进去,之后再从记录文件读,之后再新建一个文件写进去,直到记录文件中的内容读完为止,这个方法固然可行,不过后面每条记录出现的次数就不好统计了。所以,我们可以想办法尽可能的把相同的记录写到一个文件中去,这样就便于后面统计。什么方法有这个功能呢,没错,你猜对了,就是hash


下面使用的就是Daniel J.Bernstein发明的算法,也是目前很有效的哈希函数。

inline long DJBHash(std::string& str)
{
    long hash = 5381;
    for(int i=0; i<str.size(); ++i) {
        hash = ((hash << 5) + hash) + str[i];
    }
    return hash;
}

有了hash以后,那如何来分割文件呢,假设我们想把记录文件分割成num个,因此我们可以从记录文件中读取记录,之后对每一条记录使用哈希算法,会计算出一个整数,我们让这个整数对num求余,这样就可以保证同样哈希值存放在同一个文件中。具体的代码如下:

/*
 * @path: 记录文件的完整路径和名称
 * @filenum: 生成的文件个数
 */
void SegmentFile(const char *path, int filenum)
{
    long hash;
    std::string str;
    std::fstream fs, filearr[filenum];
    fs.open(path, std::fstream::in);
    while(fs>>str) {
	//对读取的记录使用哈希算法
        hash = DJBHash(str);
        hash = hash % filenum;
        if(!filearr[hash].is_open()) {
	    //为了简便,新产生的文件的文件名直接使用数字表示
            filearr[hash].open(std::to_string(hash).c_str(), 
                               std::f
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值