问题:在保留O(1)算法操作复杂性的同时,在文件中存储图形的动态邻接列表。
我正在尝试将动态双向图存储在文件中。可以添加和删除节点和边缘,操作必须为O(1)。我目前的设计是:
文件1 - 节点
每个节点存储两个整数(插入是追加和删除使用空闲列表):
文件2 - 边缘
每个边缘存储4个整数(插入是追加和删除使用空闲列表+交换,最后一个边缘用于节点更新其新索引):
File 1
)File 1
)文件3 - 链接
用作文件2中边缘位置的公开寻址哈希表。基本上,当您从File 1
读取节点时,您知道有x
个传入边和y
个传出边。有了它,您可以转到File 3
以获取File 2
中每条边的位置。因此关键是:
File 1
中的节点索引(即第一个节点为0,第二个节点为1) File 3
键的示例,如果表示为链式哈希表(遗憾的是不适合文件但不需要散列...):
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
我正在使用qHash
和QPair
对这些atm进行哈希处理,但冲突次数非常多。特别是当我将它与int
非常有效的单qHash
哈希进行比较时。由于存储的值是另一个文件的索引,探测是相当昂贵的,所以我想减少碰撞的数量。
是否有专门的哈希算法或方法用于pair of ints
,在这种情况下可以表现更好?或者当然是一种可以避免这个问题的不同方法,例如如何在文件中实现链式哈希表(我只能想到使用缓冲区,但这对于像我这样的稀疏图形来说会有点过分)?
答案 0 :(得分:0)
如果您阅读this answer上的评论,他们声称qHash
的{{1}}只会返回int
不变(这是一种相当常见的方法来排除整数在内存中的哈希表中使用)。因此,使用强大的通用哈希函数可以显着减少冲突,尽管您可能会因为附近的密钥更可能散布到磁盘上的相同区域而忽略了一些偶然的缓存优势,因此请测量而不是采用它当然,更少的碰撞意味着更好的性能。我还建议尝试int
从多个哈希值创建一个总体哈希值(仅使用+或XOR是一个非常糟糕的主意)。然后,如果您正在从磁盘读取数据,则可能存在某种页面大小 - 例如4k,8k - 您必须在该页面的任何位置读取以访问任何数据,因此如果发生碰撞,它仍然可以更好地查看已加载页面上的其他位置,而不是而不是等待从磁盘加载另一个页面。简单的线性探测可以在很多时候管理,但您可以通过回到页面的开头来进一步改进,以确保您在探测其他地方之前搜索所有内容。