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

时间:2013-12-20 02:33:34

标签: c++ hashmap

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

散列键的数量大约为200,000,000;并且每个散列键中可能的元素数量大约为100,000。

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

现在我将硬盘中的数据存储在名为hash_file.txt的文件中。该文件看起来像:

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

其中,> 1,...,> 200,000,000是原始哈希表的所有可能键; 和T1,...,T100000是每个键的所有可能元素。 注意:哈希表非常稀疏,每个键不再有几百个元素。

在此示例中,输出反向哈希表如下所示:

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

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

2 个答案:

答案 0 :(得分:1)

虽然您的问题围绕使用内存中的哈希来反转这些项目的关系,但根据评论,您真正想做的就是获取输出并且方法并不重要。

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

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

这是我使用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)

答案 1 :(得分:1)

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

#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”以这样的方式反映词典排序)