To jest bardziej pytanie dotyczące CS, ale interesujące:
Powiedzmy, że mamy 2 struktury drzewiaste z mniej więcej tymi samymi zreorganizowanymi węzłami. Jak byś znalazł
- każdy
- w pewnym sensie minimalne
kolejność operacji
MOVE(A, B)
- przenosi węzeł A pod węzeł B (z całym poddrzewem)INSERT(N, B)
- wstawia nowy węzeł N pod węzłem BDELETE (A)
- usuwa węzeł A (wraz z całym poddrzewem)
która przekształca jedno drzewo w drugie.
Mogą oczywiście zaistnieć przypadki, w których taka transformacja nie jest możliwa, trywialne jest to, że root A z dzieckiem B jest rootem B z dzieckiem A itd.). W takich przypadkach algorytm po prostu dałby wynik „ niemożliwy ”.
Jeszcze bardziej spektakularna wersja jest uogólnieniem dla sieci, tj. Kiedy zakładamy, że węzeł może występować wielokrotnie w drzewie (efektywnie mając wielu „rodziców”), a cykle są zabronione.
Zastrzeżenie: to nie jest praca domowa, w rzeczywistości pochodzi z prawdziwego problemu biznesowego i uznałem to za całkiem interesujące, zastanawiając się, czy ktoś może znać rozwiązanie.
źródło
MOVE(A,B)
wydaje się być taki sam,INSERT(A,B)
jakbyA
nie miał dzieci. Co dzieje się z dziećmi,A
jeśli tak się stanieINSERT(A,B)
? (czy będą przywiązani doA
rodzica?)Odpowiedzi:
Jest nie tylko artykuł w Wikipedii o izomorfizmie grafów (jak wskazuje Space_C0wb0y), ale także artykuł poświęcony problemowi izomorfizmu grafów . Ma sekcję,
Solved special cases
dla której znane są rozwiązania wielomianowe. Drzewa jest jednym z nich i cytuje następujące dwa odniesienia:źródło
Nie było jasne, czy porównujesz abstrakcyjne drzewa składniowe dla kodu źródłowego, dokumentów XML interpretowanych jako drzewa lub innego typu drzewa.
Istnieje wiele artykułów omawiających porównywanie drzew składniowych i obliczanie minimalnych odległości różnymi metodami. Pomysły powinny być trafne.
Dobrym artykułem jest Change Distilling , który próbuje porównać kod źródłowy dwóch abstrakcyjnych drzew składniowych i zgłosić minimalną różnicę. Artykuł mówi o konkretnej metodzie, a także zwięźle wspomina (i podaje odniesienia) do różnych podobnych technik.
Niewiele z tych algorytmów jest faktycznie realizowanych w dostępnych narzędziach do porównywania tekstu źródłowego programu komputerowego. Nasz Smart Differencer jest jednym z nich; kieruje się wyraźną gramatyką językową dla wielu języków.
źródło
Chociaż to pytanie jest stare, dodam poniżej kilka dodatkowych odniesień i algorytmów:
Ponadto istnieją biblioteki i frameworki na GitHub (w javascript), które implementują różnicowanie struktur przypominających drzewo, na przykład aplikacje obsługujące dane JSON lub drzewa XML (np. Dla MVC / MVVM po stronie klienta):
źródło
Change Detection in XML Trees: a Survey
artykułu - zawiera on listę dziesiątek algorytmów porównywania XML (czyli porównywania drzewem).Jeśli ludzie znajdą to pytanie i potrzebują czegoś zaimplementowanego dla Node.js lub przeglądarki, podaję link i przykład kodu do implementacji, którą napisałem, którą możesz znaleźć na github tutaj: ( https://github.com /hoonto/jqgram.git ) w oparciu o istniejący kod PyGram Python ( https://github.com/Sycondaman/PyGram ).
To jest odległość edycji drzewa algorytm przybliżenia , ale jest o wiele, dużo szybszy niż próba znalezienia prawdziwej odległości edycji. Przybliżenie jest wykonywane w O (n log n) czasie i O (n) przestrzeni, podczas gdy prawdziwa odległość edycji jest często O (n ^ 3) lub O (n ^ 2) przy użyciu znanych algorytmów dla rzeczywistej odległości edycji. Zobacz artykuł naukowy, z którego pochodzi algorytm PQ-Gram: ( http://www.vldb2005.org/program/paper/wed/p301-augsten.pdf )
Więc używając jqgram:
Przykład:
A to daje liczbę od 0 do 1. Im bliżej zera, tym bardziej zbliżone są dwa drzewa do jqgram. Jednym podejściem mogłoby być użycie jqgram do zawężenia kilku blisko spokrewnionych drzew spośród wielu drzew, biorąc pod uwagę jego prędkość, a następnie wykorzystanie rzeczywistej odległości edycji na kilku pozostałych drzewach, które trzeba bliżej przyjrzeć się i do tego można znaleźć pytona implementacje w celach informacyjnych lub port algorytmu Zhang & Shasha na przykład.
Zwróć uwagę, że parametry lfn i cfn określają, w jaki sposób każde drzewo powinno niezależnie określać nazwy etykiet węzłów i tablice potomne dla każdego korzenia drzewa, dzięki czemu możesz robić dziwne rzeczy, takie jak na przykład porównywanie obiektu z DOM przeglądarki. Wszystko, co musisz zrobić, to dostarczyć te funkcje wraz z każdym korzeniem, a jqgram zrobi resztę, wywołując funkcje dostarczone przez lfn i cfn, aby zbudować drzewa. W tym sensie jest (w każdym razie moim zdaniem) znacznie łatwiejszy w użyciu niż PyGram. Plus, jego Javascript, więc używaj go po stronie klienta lub serwera!
TAKŻE, aby odpowiedzieć na temat wykrywania cykli, sprawdź metodę klonowania wewnątrz jqgram, jest tam wykrywanie cykli, ale zasługa tego należy do autora klonu węzła, z którego ten element został nieco zmodyfikowany i uwzględniony.
źródło
Nazywa się to problemem korygowania drzewa do drzewa lub problemem edycji drzewa do drzewa . Większość literatury zajmującej się tym bezpośrednio odnosi się do porównywania drzew XML z jakiegoś powodu, więc wyszukanie „algorytmu różnicującego XML” daje wiele wyników. Oprócz listy linków Nikosa znalazłem te:
Kod do tego - VTracker nadal istnieje!Edycja: w rzeczywistości interesujący fragment kodu nie jest uwzględniony. To wskazało mi ...Polecam również przeczytanie lektury Wykrywanie zmian w drzewach XML: ankieta ale pochodzi z 2005 r., Więc prawie żadne z wymienionych narzędzi już nie istnieje. Porównywanie dokumentów XML jako uporządkowanych drzew z etykietami uwzględniającymi odnośniki daje najbardziej intuicyjny opis niektórych algorytmów, jakie do tej pory znalazłem (zacznij od sekcji 2.1.2).
Niestety wydaje się, że nie ma zbyt wielu dostępnych kodów open source, które to robią i nie są starożytne. Tylko wiele zbyt skomplikowanych dokumentów. : - /
źródło
Change Detection in XML Trees: a Survey
Download full-test PDF
przycisk? Może wypróbuj Sci-hub, jeśli z jakiegoś powodu jest zablokowany.