散列树结构
我刚刚在我的项目中遇到了一个场景,在该场景中,我需要将不同的树对象与已知实例进行相等性比较,并认为对任意树进行操作的某种哈希算法将非常有用。
以下面的树为例:
Ø / \
/ \
面向对象
/ | \ |
/ | \ |
OOOO
/ \
/ \
面向对象
其中每个O
代表树的节点,是一个任意对象,具有关联的哈希函数。因此问题减少到:给定树结构的节点的哈希码和已知的结构,一种用于计算整个树的(相对)无冲突哈希码的不错的算法是什么?
有关哈希函数属性的一些说明:
- 哈希函数应取决于树中每个节点的哈希码及其位置。
- 对节点的子节点重新排序 应该 明显改变生成的哈希码。
- 反映树的任何部分都 应该 明显改变生成的哈希码
如果有帮助,尽管我主要是在寻找理论上的解决方案,但我在我的项目中正在使用C#4.0,因此伪代码,描述或另一种命令性语言的代码都可以。
更新
好吧,这是我自己提出的解决方案。这里的几个答案对它有很大帮助。
每个节点(子树/叶节点)具有以下哈希函数:
public override int GetHashCode(){
int hashCode = unchecked((this.Symbol.GetHashCode() * 31 +
this.Value.GetHashCode()));
for (int i = 0; i < this.Children.Count; i++)
hashCode = unchecked(hashCode * 31 + this.Children[i].GetHashCode());
return hashCode;
}
如我所见,关于此方法的好处是,哈希码可以缓存,并且仅在节点或其后代之一更改时才重新计算。(感谢vatine和Jason Orendorff指出了这一点)。
无论如何,如果有人可以在这里对我建议的解决方案发表评论,我将不胜感激-如果它做得很好,那就很好,否则任何可能的改进都将受到欢迎。
回答:
如果要执行此操作,则可能会执行以下操作:
对于每个叶节点,计算0的串联和节点数据的哈希。
对于每个内部节点,请从左到右计算1的串联和任何本地数据的哈希(NB:可能不适用)以及子代的哈希。
每当您进行任何更改时,这都会导致树的级联,但这可能不足以使开销值得。如果与更改量相比更改相对不频繁,则使用加密安全的哈希甚至更有意义。
Edit1:
还可以在每个节点上向每个节点添加“哈希有效”标志,并在树上沿树传播“假”(或“哈希无效”并向树传播“真”)。这样,有可能在需要树哈希时避免完全重新计算,并且有可能避免未使用的多个哈希计算,而在需要时可能会有更少的可预测时间获得哈希。
Edit3:
如果GetHashCode的结果可以为0,则Noldorin在问题中建议的哈希码看起来很可能会发生冲突。本质上,没有办法用“符号”来区分由单个节点组成的树。哈希”
30和“值哈希”
25,以及两节点树,其中根的“符号哈希”为0,“值哈希”为30,子节点的总哈希为25。示例完全是是发明的,我不知道预期的哈希范围是多少,所以我只能对在所提供的代码中看到的内容进行评论。
使用31作为乘法常数是好的,因为它将导致在非位边界上发生任何溢出,尽管我认为,如果树中有足够的子级和可能的对抗性内容,则可能对MAY早期哈希的项的哈希贡献由以后的散列项目主导。
但是,如果散列在预期数据上表现良好,则看起来好像可以完成工作。它肯定比使用加密哈希(在下面的示例代码中完成)要快。
Edit2: 对于特定的算法和所需的最小数据结构,类似于以下内容(Python,翻译成任何其他语言应该相对容易)。
#!/ usr / bin / env python导入Crypto.Hash.SHA
类节点:
def __init__(self,parent = None,contents =“”,children = []):
self.valid =假
self.hash =假
self.contents =内容
self.children =孩子
def append_child(自己,孩子):
self.children.append(child)
self.invalidate()
def invalidate(个体):
self.valid =假
如果为self.parent:
self.parent.invalidate()
def gethash(个体经营):
如果self.valid:
返回self.hash
消化器= crypto.hash.SHA.new()
摘要更新(self.contents)
如果是self.children:
对于self.children中的孩子:
summaryer.update(child.gethash())
self.hash =“ 1” + digester.hexdigest()
其他:
self.hash =“ 0” + digester.hexdigest()
返回self.hash
def setcontents(个体):
self.valid =假
返回self.contents
以上是 散列树结构 的全部内容, 来源链接: utcz.com/qa/399020.html