我想知道一种相对简单的方式来生成复杂的C结构的哈希(在我的情况下,它构成一个图)。 “简单”是指,如果可能,而不必遍历它形成的所有节点。之后,我的目标是检查两个结构是否由于哈希值而相同,而且还要对它们进行有序排序。
例如,存在用于数字或字符串的函数和算法,但是我不知道对结构进行处理的好方法。你会推荐什么?
Git版本控制系统具有您所描述的哈希系统。一个Git仓库是一个directed acyclic graph。每个提交都是一个节点。
每个提交都有一个ID。该ID是哈希。它对节点的内容以及其所有连接的哈希进行哈希处理。
例如,如果进行提交,则其ID将是其内容的哈希(sha256校验和)。我们将其称为提交A。如果您在A之上进行另一次提交,则其ID将是提交内容的哈希加上A的哈希。依此类推。
A hash(A's content)
^
|
B hash(hash(B's content) + A's hash)
^
|
C hash(hash(C's content) + B's hash)
如果您有一个合并,其中一个合并提交具有两个连接,它将使用两个节点的哈希。
C
^
|\
D E
^ ^
|/
F hash(hash(F's contents) + D's hash + E's hash)
最后,Git还将节点存储在以其提交ID为键的哈希中,以通过ID查找O(1)节点。
F的哈希取决于D,E的哈希取决于C的哈希,而C的哈希取决于B的哈希,而B的哈希取决于A的哈希。 F的哈希取决于整个存储库的内容。如果过去的任何提交更改(无论是按内容还是按连接),则F的哈希将无效。
这就是Git能够如此迅速地比较存储库中的更改的方式。它只需要比较每个分支的尖端的提交ID即可知道是否存在差异,然后向后进行操作,直到找到一个通用的提交ID。它使用该图向后追溯提交历史记录,并使用散列查找是否有共同的提交ID。
此技术仅适用,因为Git的图形是DAG。连接只能指向一种方式(定向),而没有循环(非循环)。也许这适用于您的情况,或者您可以调整技术。