人々がこの質問を見つけて、Node.jsまたはブラウザー用に実装されたものが必要な場合に備えて、私が書いた実装のリンクとコード例を提供します。これはgithubで見つけることができます:(https://github.com /hoonto/jqgram.git)既存のPyGram Pythonコード(https://github.com/Sycondaman/PyGram)に基づいています。
これはツリー編集距離近似アルゴリズムですが、実際の編集距離を見つけようとするよりもはるかに高速です。近似はO(n log n)時間とO(n)空間で実行されますが、真の編集距離は、多くの場合、真の編集距離の既知のアルゴリズムを使用してO(n ^ 3)またはO(n ^ 2)です。PQ-Gramアルゴリズムの元となった学術論文を参照してください:(http://www.vldb2005.org/program/paper/wed/p301-augsten.pdf)
したがって、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の間の数を与えます。ゼロに近いほど、2つのツリーはjqgramに密接に関連しています。1つのアプローチは、jqgramを使用して、速度を考慮して多くのツリーの中から密接に関連するいくつかのツリーを絞り込み、残りのいくつかのツリーで実際の編集距離を利用して、詳細に調べる必要があります。そのために、Pythonを見つけることができます。たとえば、Zhang&Shashaアルゴリズムの参照または移植のための実装。
lfnパラメーターとcfnパラメーターは、各ツリーがノードラベル名と各ツリールートの子配列を個別に決定する方法を指定するため、たとえば、オブジェクトをブラウザーDOMと比較するなどのファンキーなことができることに注意してください。あなたがする必要があるのは、各ルートと一緒にそれらの関数を提供することだけであり、jqgramが残りを行い、ツリーを構築するためにあなたのlfnとcfnが提供する関数を呼び出します。その意味で、(とにかく私の意見では)PyGramよりもはるかに使いやすいです。さらに、そのJavascriptなので、クライアント側またはサーバー側で使用してください。
また、サイクル検出に関して答えるために、jqgram内のクローンメソッドをチェックしてください。そこにはサイクル検出がありますが、その功績は、その部分がわずかに変更されて含まれているノードクローンの作成者にあります。
MOVE(A,B)
同じように見えるINSERT(A,B)
場合はA
子を持っていません。A
もしそうしたら、子供たちはどうなりINSERT(A,B)
ますか?(それらはA
の親に添付されますか?)