[algorithm] 두 트리 구조를 동일하게 만들기위한 최소 작업 계산
이것은 CS 질문에 더 가깝지만 흥미로운 질문입니다.
동일한 노드가 다소 재구성 된 2 개의 트리 구조가 있다고 가정 해 보겠습니다. 어떻게 찾 겠어요
- 어떤
- 어떤 의미에서는 최소한
작업 순서
MOVE(A, B)
-노드 A를 노드 B 아래로 이동 (전체 하위 트리 포함)INSERT(N, B)
– 노드 B 아래에 새 노드 N을 삽입합니다.DELETE (A)
-노드 A 삭제 (전체 하위 트리 포함)
하나의 나무를 다른 나무로 변환합니다.
분명히 그러한 변환이 불가능한 경우가있을 수 있습니다. 하위 B가있는 루트 A에서 하위 A가있는 루트 B까지 사소한 경우가 있습니다.) 이러한 경우 알고리즘은 단순히 ” 불가능 ” 이라는 결과를 제공합니다 .
훨씬 더 멋진 버전은 네트워크에 대한 일반화입니다. 즉, 노드가 트리에서 여러 번 발생할 수 있다고 가정하고 (효과적으로 여러 “부모”가 있음)주기는 금지되어 있습니다.
면책 조항 : 이것은 숙제 가 아니며 실제로 실제 비즈니스 문제에서 비롯된 것이며 누군가가 해결책을 알고 있는지 궁금해하는 것이 매우 흥미 롭다는 것을 알았습니다.
답변
그래프 동형에 관한 Wikipedia 기사 (Space_C0wb0y가 지적한대로)뿐만 아니라 그래프 동형 문제 에 대한 전용 기사도 있습니다 . Solved special cases
다항식 시간 솔루션이 알려진 섹션 이 있습니다. 트리는 그중 하나이며 다음 두 가지 참조를 인용합니다.
- PJ Kelly, “나무에 대한 합동 정리”Pacific J. Math., 7 (1957) pp. 961–968
- Aho, Alfred V .; Hopcroft, John; Ullman, Jeffrey D. (1974), 컴퓨터 알고리즘의 설계 및 분석, 읽기, MA : Addison–Wesley.
답변
소스 코드, 트리로 해석되는 XML 문서 또는 다른 유형의 트리에 대해 추상 구문 트리를 비교하고 있는지 확실하지 않았습니다.
구문 트리를 비교하고 다양한 방법으로 최소 거리를 계산하는 것에 대해 논의하는 많은 논문이 있습니다. 아이디어는 관련성이 있어야합니다.
좋은 논문은 Change Distilling으로 , 두 개의 추상 구문 트리에 대한 소스 코드를 비교하고 최소한의 차이를보고하려고합니다. 이 문서는 특정 방법에 대해 이야기하고 다양한 유사한 기술에 대해 간략하게 언급하고 참조를 제공합니다.
이러한 알고리즘 중 컴퓨터 프로그램 소스 텍스트를 비교하는 데 사용할 수있는 도구에서 실제로 실현되는 것은 거의 없습니다. 우리의 Smart Differencer 는 그중 하나입니다. 많은 언어에 대한 명시적인 언어 문법에 의해 구동됩니다.
답변
이 질문은 오래되었지만 아래에 몇 가지 참조와 알고리즘을 더 추가하겠습니다.
- X-Diff : XML 문서를위한 효과적인 변경 감지 알고리즘, Yuan Wang, David J. DeWitt, Jin-Yi Cai
- KF-Diff + : XML 문서를위한 매우 효율적인 변경 감지 알고리즘
- diffX : 다중 버전 XML 문서의 변경 사항을 감지하는 알고리즘
- XML 트리의 변경 감지 : 설문 조사, Luuk Peters
- 트리 데이터 구조의 유사성
또한, JSON 데이터 또는 XML 트리 (예 : 클라이언트 측 MVC / MVVM의 경우)를 처리하는 애플리케이션의 경우 트리와 유사한 구조의 차이를 구현하는 GitHub (자바 스크립트)에는 라이브러리와 프레임 워크가 있습니다.
답변
사람들이이 질문을 발견하고 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 사이의 숫자를 제공합니다. 0에 가까울수록 두 나무가 jqgram을 더 가깝게 보입니다. 한 가지 접근 방식은 jqgram을 사용하여 속도가 주어진 여러 트리 중에서 밀접하게 관련된 여러 트리를 좁힌 다음 면밀한 검사가 필요한 나머지 몇 개의 트리에 대한 실제 편집 거리를 활용하여 파이썬을 찾을 수 있습니다. 예를 들어 Zhang & Shasha 알고리즘의 참조 또는 포트에 대한 구현.
lfn 및 cfn 매개 변수는 각 트리가 각 트리 루트에 대한 노드 레이블 이름과 자식 배열을 독립적으로 결정하는 방법을 지정하여 예를 들어 개체를 브라우저 DOM과 비교하는 것과 같은 펑키 한 작업을 수행 할 수 있습니다. 각 루트와 함께 해당 함수를 제공하기 만하면 jqgram이 나머지를 수행하여 lfn 및 cfn 제공 함수를 호출하여 트리를 구축합니다. 따라서 그런 의미에서 PyGram보다 사용하기가 훨씬 쉽습니다. 또한 Javascript이므로 클라이언트 또는 서버 측을 사용하십시오!
또한주기 감지와 관련하여 대답하려면 jqgram 내부의 복제 방법을 확인하십시오. 거기에주기 감지가 있지만 그 부분이 약간 수정되고 포함 된 node-clone의 작성자에게 있습니다.
답변
이를 트리 대 트리 수정 문제 또는 트리 대 트리 편집 문제라고 합니다. 이 문제를 다루는 대부분의 문헌은 어떤 이유로 XML 트리를 비교하는 것과 관련이 있으므로 “XML diffing algorithm”을 검색하면 많은 결과를 얻을 수 있습니다. Nikos의 링크 목록 외에도 다음을 발견했습니다.
- 구조화 된 텍스트 문서의 세분화 된 변경 감지 (2014)
- 수준별 변경 감지 (CDL) : XML 문서의 변경을 감지하는 효율적인 알고리즘 (2010)
- XML 문서를 참조 인식 레이블이있는 정렬 된 트리로 비교 (2011)
이에 대한 코드 -VTracker가 여전히 존재합니다!편집 : 실제로 흥미로운 코드는 포함되어 있지 않습니다. 이것은 나를 가리켰다 … - UMLDiff : 객체 지향 설계 차이를위한 알고리즘 (2005).
- 트리 편집 거리 및 역 추적 재검토 : 튜토리얼 (2018)- “고전적인”솔루션 인 것처럼 보이지만 모든 하위 트리를 다른 모든 하위 트리.
또한 XML 트리의 변경 감지 : 설문 조사를 읽는 것이 좋습니다 . 하지만 2005 년에 작성된 것이기 때문에 언급 한 도구가 더 이상 존재하지 않습니다. XML 문서를 참조 인식 레이블이있는 정렬 된 트리로 비교 지금까지 찾은 알고리즘 중 일부에 대한 가장 직관적 인 설명이 있습니다 (섹션 2.1.2에서 시작).
안타깝게도이를 수행하는 오픈 소스 코드가 많지 않은 것 같고 오래되지 않았습니다. 지나치게 복잡한 논문이 많습니다. :-/