C 从大文件中查找唯一值

C 从大文件中查找唯一值,c,algorithm,memory-management,hash,bigdata,C,Algorithm,Memory Management,Hash,Bigdata,我有一个大文件(比如10 TB),包含MD5哈希流(其中包含重复项),我有一个10MB的内存(非常有限)和无限的硬盘空间。使用给定条件查找所有唯一散列(消除重复)。请帮助,这显然不是一个家庭作业问题您可以使用外部排序算法(例如,使用a)对哈希进行排序,然后只需遍历文件并跳过任何与最近的哈希相等的哈希 hash mostRecentHash; while(fileHasHashes) { temp = fileWithDuplicates.readHash(); if(!hashe

我有一个大文件(比如10 TB),包含MD5哈希流(其中包含重复项),我有一个10MB的内存(非常有限)和无限的硬盘空间。使用给定条件查找所有唯一散列(消除重复)。请帮助,这显然不是一个家庭作业问题

您可以使用外部排序算法(例如,使用a)对哈希进行排序,然后只需遍历文件并跳过任何与最近的哈希相等的哈希

hash mostRecentHash;
while(fileHasHashes) {
    temp = fileWithDuplicates.readHash();
    if(!hashesAreEqual(mostRecentHash, temp)) {
        mostRecentHash = temp;
        fileWithoutDuplicates.writeHash(mostRecentHash);
    }
}

如果性能无关紧要,并且您的文件系统没有限制,那么您可以简单地为每个哈希创建一个文件。如果在创建过程中遇到
EEXIST
,则您有一个副本,可以跳过它

for (each hash) {
    r = open(hash_to_filename(hash), O_CREAT|O_EXCL);
    if (r < 0) {
        if (errno == EEXIST) continue;
        perror(hash);
        exit(EXIT_FAILURE);
    }
    close(r);
    output(hash);
}
for(每个散列){
r=打开(散列到文件名(散列),O_创建| O_排除);
if(r<0){
如果(errno==EEXIST)继续;
perror(hash);
退出(退出失败);
}
关闭(r);
输出(散列);
}
这样做的优点是它保留了哈希值在流中首次出现的顺序


此解决方案的实际性能取决于文件系统的性能。如果文件组织在一个B-树中,那么性能大约是O(N log(N))。如果文件系统使用哈希表来组织文件,则性能预计为O(N),但这取决于冲突发生的频率(由于磁盘访问,常数因子很高)。

我喜欢Zim Zam的解决方案……提出了一个小的变化

如果我们可以假设指纹在128位空间上均匀分布,那么
我们是否可以使用Bucket sort之类的方法将指纹存储到(较小的)Bucket文件中,对Bucket文件进行单独排序,然后使用堆将Bucket文件合并到一个已排序的文件中?这可能会降低nlogn成本。

“这显然不是家庭作业问题”性能重要吗?我的意思是可以使用一些O(n^2)解决方案吗?@AdelQodmani对于10*TB的16字节哈希,O(n^2)和O(nlogn)之间的性能差异是天文数字。这显然是一个不错的解决方案。外部多相合并排序是实现这一点的完美算法+1+1删除了我的答案,因为这是一个更好的解决方案。那么为什么他要我使用无限数据库?如果你应该使用数据库,那么在添加之前,只需检查数据库中是否已经存在哈希
从hash\u表中选择hash,其中hash=currentHash
,如果返回null/false,则
插入hash\u表(hash)值(currentHash)