用Cpp或其他快速语言反转大型哈希表

Invert Large Hash Table in Cpp or other fast language

本文关键字:大型 哈希表 语言 Cpp 其他      更新时间:2023-10-16

我正在寻找高效的C++(或其他快速)来反转一个巨大的哈希表。

散列密钥的数量大约为200000000;并且每个散列密钥中的可能元素的数量为100000的数量级。

我想知道什么是(有效地)反转这样的表的好方法,这样现在元素就是键,键就是元素。

现在,我的硬盘驱动器中的数据存储在一个名为hash_file.txt的文件中

>1
T1
T3
T4
T100
>2
T4
T77
T9980
etc.

其中,>1,…,>200000000是原始哈希表的所有可能的密钥;以及T1,。。。,T100000是每个键的所有可能元素。注意:哈希表非常稀疏,每个键最多只有几百个元素。

输出的反向哈希表在本例中如下所示:

>T1
1
>T3
1
>T100
1
>T4
1
2
>T77
2
>T9980
2

我尝试了一些天真的代码,花了很长时间,内存用完了,所以我正在寻找好的建议。

这是一种非常简单的方法;值得一试(记得在启用优化的情况下进行构建,但最好不要禁用assert;-))。

#include <iostream>
#include <vector>
#include <cassert>
int main()
{
char c;
int n;
int key = -1;
const int max_t = 100000;
std::vector<std::vector<int>> v(max_t + 1);
while (std::cin >> c >> n)
if (c == '>')
key = n;
else
{
assert(c == 'T');
assert(key != -1);
assert(0 <= n && n < v.size());
v[n].push_back(key);
}
assert(std::cin.eof());
for (int i = 0; i < v.size(); ++i)
{
if (v[i].empty()) continue;
std::cout << ">T" << i << 'n';
for (int j = 0; j < v[i].size(); ++j)
std::cout << v[i][j] << 'n';
}
}

(输出顺序是数字的,而不是像你的问题中那样词典化的……如果你关心的话,你可以寻找/编写一个算法来迭代"i",以镜像词典化的顺序)

尽管你的问题是围绕着使用内存中的哈希来反转这些项的关系来提出的,但根据注释,你真正想做的只是获得输出,而方法并不重要。

由于您正在处理的数据量很大,因此无论您选择何种数据结构,都可能无法将其全部加载到内存中。因此,您将需要一种方法,该方法一次只将部分数据包含到内存中。

我倾向于使用数据库来完成这样的任务。创建一个包含两列的表——现有的"key"列和"T"value列。在值列上加一个索引。然后运行一个查询,该查询将为您提供所需的输出。

以下是我使用Postgresql:创建的一个示例

create table bigmap (
key integer,
value text
);
create index on bigmap(value);
insert into bigmap(key,value) values (1, 'T1');
insert into bigmap(key,value) values (1, 'T3');
insert into bigmap(key,value) values (1, 'T4');
insert into bigmap(key,value) values (1, 'T100');
insert into bigmap(key,value) values (2, 'T4');
insert into bigmap(key,value) values (2, 'T77');
insert into bigmap(key,value) values (2, 'T9980');
select value,key from bigmap order by value,key;
value | key
-------+-----
T1    |   1
T100  |   1
T3    |   1
T4    |   1
T4    |   2
T77   |   2
T9980 |   2
(7 rows)

从您的输入文件填充数据库应该相对简单。你可以用C++编写一个程序来完成这项工作,但根据你想多久做一次,你最好使用例如perl

使用数据库的优点是,它们已经有了对此类数据进行排序和索引的高效例程,并且还内置了在可用内存不足时使用临时文件准备大型查询结果的处理。

此外,如果你想找到特定T值的所有密钥,这很容易:

select value,key from bigmap where value='T100';
value | key
-------+-----
T100  |   1
(1 row)