En caso de que la gente encuentre esta pregunta y necesite algo implementado para Node.js o el navegador, proporciono un enlace y un ejemplo de código para una implementación que he escrito que puede encontrar en github aquí: ( https://github.com /hoonto/jqgram.git ) basado en el código PyGram Python existente ( https://github.com/Sycondaman/PyGram ).
Este es un algoritmo de aproximación de distancia de edición de árbol , pero es mucho, mucho más rápido que intentar encontrar la distancia de edición real. La aproximación se realiza en el tiempo O (n log n) y el espacio O (n), mientras que la distancia de edición real suele ser O (n ^ 3) u O (n ^ 2) utilizando algoritmos conocidos para la distancia de edición real. Vea el artículo académico del que proviene el algoritmo PQ-Gram: ( http://www.vldb2005.org/program/paper/wed/p301-augsten.pdf )
Entonces usando jqgram:
Ejemplo:
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);
});
Y eso le da un número entre 0 y 1. Cuanto más cerca de cero, más estrechamente relacionados se ven los dos árboles con jqgram. Un enfoque podría ser usar jqgram para reducir varios árboles estrechamente relacionados de entre muchos árboles dada su velocidad, luego utilizar la distancia de edición real en los pocos árboles restantes que necesita para inspeccionar más de cerca, y para eso puede encontrar python implementaciones para referencia o puerto del algoritmo Zhang & Shasha, por ejemplo.
Tenga en cuenta que los parámetros lfn y cfn especifican cómo cada árbol debe determinar los nombres de las etiquetas de los nodos y la matriz secundaria para cada raíz del árbol de forma independiente para que pueda hacer cosas divertidas como comparar un objeto con un DOM del navegador, por ejemplo. Todo lo que necesita hacer es proporcionar esas funciones junto con cada raíz y jqgram hará el resto, llamando a sus funciones proporcionadas lfn y cfn para construir los árboles. Entonces, en ese sentido, es (en mi opinión de todos modos) mucho más fácil de usar que PyGram. Además, es Javascript, ¡así que utilícelo del lado del cliente o del servidor!
TAMBIÉN, para responder con respecto a la detección de ciclos, consulte el método de clonación dentro de jqgram, hay detección de ciclos allí, pero el crédito es para el autor del clon de nodo a partir del cual esa pieza fue ligeramente modificada e incluida.
MOVE(A,B)
parece ser lo mismo queINSERT(A,B)
siA
no tuviera hijos. ¿Qué pasa con los hijos deA
si uno lo haceINSERT(A,B)
? (¿Estarán apegados alA
padre de '?)