Algorithm 计算使两个树结构相同的最小操作
这更像是一个CS问题,但也是一个有趣的问题: 假设我们有两个树结构,它们或多或少地重组了相同的节点。你会怎么发现Algorithm 计算使两个树结构相同的最小操作,algorithm,tree,comparison,diff,computer-science,Algorithm,Tree,Comparison,Diff,Computer Science,这更像是一个CS问题,但也是一个有趣的问题: 假设我们有两个树结构,它们或多或少地重组了相同的节点。你会怎么发现 任何 从某种意义上说是最小的 操作顺序 移动(A,B)将节点A移动到节点B下(连同整个子树) 插入(N,B)-在节点B下插入一个新的节点N DELETE(A)-删除节点A(连同整个子树) 将一棵树转换为另一棵树 很明显,在某些情况下,这样的转换是不可能的,比如根A和子B到根B和子A等)。在这种情况下,算法只会给出一个“不可能”的结果 更引人注目的版本是对网络的推广,即当我们假设一
将节点A移动到节点B下(连同整个子树)移动(A,B)
-在节点B下插入一个新的节点N插入(N,B)
-删除节点A(连同整个子树)DELETE(A)
免责声明:这不是一个家庭作业,实际上它来自一个真实的商业问题,我觉得很有趣,想知道是否有人知道一个解决方案。不仅有一篇关于图同构的维基百科文章(正如Space_C0wb0y所指出的),而且还有一篇关于这个问题的专门文章。它有一个部分
解决了已知多项式时间解的特殊情况
。树木就是其中之一,它引用了以下两个参考文献:
- 阿霍,阿尔弗雷德五世。;约翰·霍普克罗夫特;厄尔曼,杰弗里D.(1974),《计算机算法的设计与分析》,雷丁,硕士:艾迪生-韦斯利
这些算法中很少有在比较计算机程序源文本的可用工具中实现的。我们是其中之一;它是由许多语言的显式语言语法驱动的。如果人们发现这个问题,需要为Node.js或浏览器实现一些东西,我将提供一个链接和代码示例,您可以在github上找到它:()基于现有的PyGram Python代码() 这是一个树编辑距离近似算法,但它比试图找到真正的编辑距离要快得多。近似在O(n logn)时间和O(n)空间中执行,而使用已知的真实编辑距离算法,真实编辑距离通常为O(n^3)或O(n^2)。参见PQ Gram算法来源的学术论文:() 因此,使用jqgram: 例如:
var jq = require("jqgram").jqgram;
var root1 = {
"thelabel": "a",
"thekids": [
{ "thelabel": "b",
"thekids": [
{ "thelabel": "c" },
{ "thelabel": "d" }
]},
{ "thelabel": "e" },
{ "thelabel": "f" }
]
}
var root2 = {
"name": "a",
"kiddos": [
{ "name": "b",
"kiddos": [
{ "name": "c" },
{ "name": "d" },
{ "name": "y" }
]},
{ "name": "e" },
{ "name": "x" }
]
}
jq.distance({
root: root1,
lfn: function(node){ return node.thelabel; },
cfn: function(node){ return node.thekids; }
},{
root: root2,
lfn: function(node){ return node.name; },
cfn: function(node){ return node.kiddos; }
},{ p:2, q:3 },
function(result) {
console.log(result.distance);
});
这会给你一个介于0和1之间的数字。越接近零,这两棵树就越接近jqgram。一种方法可能是使用jqgram从许多树中缩小几个密切相关的树(给定其速度),然后在剩下的几棵树上利用真实的编辑距离,您需要仔细检查这些树,为此,您可以找到python实现以供参考,或者例如Zhang&Shasha算法的端口
请注意,lfn和cfn参数指定了每个树应该如何独立地确定每个树根的节点标签名称和子数组,以便您可以执行一些有趣的操作,例如将对象与浏览器DOM进行比较。您所需要做的就是将这些函数与每个根一起提供,其余的由jqgram完成,调用lfn和cfn提供的函数来构建树。因此,从这个意义上讲,它(无论如何在我看来)比PyGram更容易使用。另外,它的Javascript,所以使用它的客户端或服务器端
另外,为了回答有关循环检测的问题,请查看jqgram中的克隆方法,那里有循环检测,但这要归功于节点克隆的作者,从中对该部分进行了轻微修改并包括在内。虽然这个问题很老,但我将在下面添加一些参考和算法: 此外,GitHub上的库和框架(javascript)实现了树状结构的差异化,例如处理JSON数据或XML树的应用程序(例如客户端MVC/MVVM):
这称为树到树校正问题或树到树编辑问题。由于某些原因,大多数关于这方面的文献都明确地涉及到比较XML树,因此搜索“XML扩散算法”会产生很多结果。除了Nikos的链接列表,我还发现了以下内容:
- (2014年)
- (2010年)
- (2011)此代码仍然存在!编辑:实际上,有趣的代码没有包括在内。这让我想到
- (2005年)
- (2018)-看起来是张沙沙算法的一个很好的教程,这似乎是“经典”的解决方案,但时间复杂度很高,因为它将每个子树与每个其他子树进行比较
移动