C++ 整数对的哈希算法
问题是:在文件中存储图形的动态邻接列表,同时保留操作的O(1)算法复杂性 我正在尝试将动态双向图形存储在文件中。可以添加和删除节点和边,并且操作必须为O(1)。我目前的设计是: 文件1-节点 每个节点存储两个整数(插入是附加,删除使用自由列表):C++ 整数对的哈希算法,c++,algorithm,qt,hash,graph,C++,Algorithm,Qt,Hash,Graph,问题是:在文件中存储图形的动态邻接列表,同时保留操作的O(1)算法复杂性 我正在尝试将动态双向图形存储在文件中。可以添加和删除节点和边,并且操作必须为O(1)。我目前的设计是: 文件1-节点 每个节点存储两个整数(插入是附加,删除使用自由列表): 传入边数 输出边数 文件2-边缘 每边存储4个整数(插入是附加和删除使用自由列表+与节点的最后一条边交换以更新其新索引): 从节点(标记到文件1) 从索引(即第三条传入边) 到节点(指向文件1) 索引(即第二个输出边) 文件3-链接 用作文件2
- 传入边数
- 输出边数
- 从节点(标记到
)文件1
- 从索引(即第三条传入边)
- 到节点(指向
)文件1
- 索引(即第二个输出边)
文件1
读取节点时,您知道有x
传入边和y
传出边。这样,您可以转到文件3
,以获取文件2中这些边的位置。因此,关键在于:
文件1中节点的索引(即0表示第一个节点,1表示第二个节点)
- 0如果您通读上的注释,它们声称
int
的qHash
只返回未更改的int
(这是一种相当常见的散列整数的方法,用于内存散列表中的无要求使用)。因此,使用强大的通用散列函数可以显著减少冲突,尽管您可能会无意中获得一些缓存好处,即附近的密钥更有可能散列到磁盘上的同一区域,所以请务必进行测量,而不是想当然地认为冲突越少,性能越好。我还建议尝试boost::hash\u combine
从多个散列值创建一个整体散列(仅使用+或XOR是一个非常糟糕的主意)。然后,如果您从磁盘读取,可能会有某种页面大小(例如4k、8k),您必须读入这些页面才能访问该页面上任何位置的任何数据,因此,如果发生冲突,最好查看已加载页面的其他位置,而不是等待从磁盘加载另一个页面。简单的线性探测在很多时候,但是,您可以通过返回到页面的开头来进一步改进这一点,以确保在搜索其他位置之前搜索了所有内容。我已经测试了各种针对整数对的哈希算法,包括now hash_combine,但QPair的qHash似乎仍优于所有其他算法。对于系数2.1,似乎根本不会产生非常理想的碰撞(其他因素需要更高的系数)。由于系数较低,碰撞上升得相当快。我尝试过的大约六种算法也是如此。不过,关于页面大小的一点很好,这肯定有助于缓解对磁盘读取过多的担忧。请参阅,这是一种相当好的散列任意数量整数的方法。@JimMischel哇,对于我的情况,这确实是一种很棒的散列算法!最后是优于qHash的内容。:-)另外,通过稍微调整它,我获得了更好的结果(我使用了3个素数而不是2个素数)。
Keys (indices from `File 1` + 0 <= index < number of edgesfrom `File 1`, not actually stored)
1 | 0 1 2
2 | 0 1
3 |
4 | 0
5 | 0 1 2