Якщо люди знаходять це запитання і потребують чогось реалізованого для 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. Чим ближче до нуля, тим тісніше пов'язані два дерева до jqgram. Одним із підходів може бути використання jqgram для звуження кількох тісно пов’язаних між собою дерев з-поміж багатьох дерев, враховуючи його швидкість, а потім використовувати справжню відстань редагування на кількох деревах, що залишилися, які вам потрібно уважніше оглянути, і для цього ви можете знайти python реалізації для посилання або порту алгоритму Чжан і Шаша, наприклад.
Зауважте, що параметри lfn та cfn визначають, як кожне дерево має самостійно визначати імена міток вузлів та дочірній масив для кожного кореня дерева, щоб ви могли робити такі забавні речі, як порівняння об'єкта з DOM браузера, наприклад. Все, що вам потрібно зробити, - це надати ці функції разом із кожним коренем, а все інше зробить jqgram, викликаючи ваші функції lfn та cfn для побудови дерев. Тож у цьому сенсі (на мій погляд у будь-якому випадку) набагато простіший у використанні, ніж PyGram. Плюс, його Javascript, тому використовуйте його на клієнтській або серверній стороні!
ТАКОЖ, щоб відповісти щодо виявлення циклу, перевірте метод клонування всередині jqgram, там є виявлення циклу, але заслуга в цьому належить автору вузла-клону, з якого цей фрагмент був трохи змінений і включений.
MOVE(A,B)
здається таким самим,INSERT(A,B)
нібиA
не має дітей. Що станеться з дітьми,A
якщо хтось так зробитьINSERT(A,B)
? (вони будуть прив'язані доA
батьків?)