Mam kilka obiektów w płaskiej strukturze. Obiekty te mają ID
i do ParentID
własności, więc mogą być umieszczone na drzewach. Nie są w określonej kolejności. Każda ParentID
właściwość niekoniecznie jest zgodna z ID
w strukturze. Dlatego może to być kilka drzew wyłaniających się z tych obiektów.
Jak przetworzyłbyś te obiekty, aby stworzyć powstałe drzewa?
Nie jestem tak daleko od rozwiązania, ale jestem pewien, że jest dalekie od optymalnego ...
Muszę utworzyć te drzewa, aby następnie wstawić dane do bazy danych we właściwej kolejności.
Brak odniesień cyklicznych. Węzeł jest RootNode, gdy ParentID == null lub gdy nie można znaleźć ParentID w innych obiektach
algorithm
tree
language-agnostic
Costo
źródło
źródło
Odpowiedzi:
Przechowuj identyfikatory obiektów w tabeli skrótów mapujących na określony obiekt. Wylicz wszystkie obiekty i znajdź ich rodzica, jeśli istnieje, i odpowiednio zaktualizuj jego wskaźnik nadrzędny.
źródło
W oparciu o odpowiedź Mehrdada Afshariego i komentarz Andrew Hanlona dotyczący przyspieszenia, oto moje podejście.
Ważna różnica w stosunku do pierwotnego zadania: Węzeł główny ma identyfikator == parentID.
źródło
Oto prosty algorytm JavaScript do analizowania płaskiej tabeli w strukturę drzewa nadrzędnego / podrzędnego, która działa w czasie N:
źródło
console.log(JSON.stringify(root, null, 2));
aby ładnie wydrukować wynik.Rozwiązanie w Pythonie
Na przykład:
Produkuje:
źródło
def recurse(id, pages): for row in rows: if row['id'] == id: print(f'''{row['id']}:{row['parent_id']} {row['path']} {row['title']}''') recurse(row['id'], rows)
Wersja JS, która zwraca jeden katalog główny lub tablicę korzeni, z których każdy będzie miał właściwość tablicową Children zawierającą powiązane dzieci. Nie zależy od uporządkowanego wejścia, przyzwoicie zwarty i nie używa rekurencji. Cieszyć się!
źródło
Znalazłem niesamowitą wersję JavaScript tutaj: http://oskarhane.com/create-a-nested-array-recursively-in-javascript/
Powiedzmy, że masz taką tablicę:
I chcesz mieć obiekty zagnieżdżone w następujący sposób:
Oto funkcja rekurencyjna, która to umożliwia.
Zastosowanie:
źródło
Dla wszystkich zainteresowanych wersją C # rozwiązania Eugene'a, pamiętaj, że lista węzłów jest dostępna jako mapa, więc zamiast tego użyj Dictionary.
Pamiętaj, że to rozwiązanie działa tylko wtedy, gdy tabela jest posortowana według parent_id .
Węzeł jest zdefiniowany w następujący sposób.
źródło
new Node { parent_id = 7, id = 9 },
uniemożliwianode_list.Add(item.id, item);
ukończenie, ponieważ klucz nie może się powtórzyć; to literówka; więc zamiast id = 9 wpisz id = 8Ogólne rozwiązanie napisałem w C # luźno na podstawie odpowiedzi @Mehrdad Afshari:
źródło
Oto java rozwiązanie odpowiedzi autorstwa Mehrdada Afshariego.
źródło
Choć wydaje mi się to niejasne, prawdopodobnie stworzyłbym mapę z identyfikatora do rzeczywistego obiektu. W pseudo-java (nie sprawdzałem czy działa / kompiluje się) może to być coś takiego:
I żeby sprawdzić każdego rodzica:
Używając ponownie
getRealObject(ID)
i wykonując mapę od obiektu do kolekcji obiektów (lub ich identyfikatorów), otrzymujesz również mapę rodzic-> dzieci.źródło
Mogę to zrobić w 4 liniach kodu i czasie O (n log n), zakładając, że Dictionary jest czymś w rodzaju TreeMap.
EDYCJA : Ok, a teraz czytam, że niektóre identyfikatory rodzicielskie są fałszywe, więc zapomnij o powyższym i zrób to:
źródło
Większość odpowiedzi zakłada, że chcesz to zrobić poza bazą danych. Jeśli Twoje drzewa są z natury względnie statyczne i musisz w jakiś sposób zmapować je do bazy danych, możesz rozważyć użycie zagnieżdżonych reprezentacji zbiorów po stronie bazy danych. Sprawdź książki autorstwa Joe Celko (lub tutaj, aby uzyskać przegląd autorstwa Celko).
Jeśli mimo to jesteś powiązany z Oracle DBS, sprawdź ich CONNECT BY, aby zapoznać się z prostymi podejściami SQL.
W obu przypadkach można całkowicie pominąć mapowanie drzew przed załadowaniem danych do bazy danych. Pomyślałem, że zaoferuję to jako alternatywę, może to być całkowicie nieodpowiednie dla twoich konkretnych potrzeb. Cała część oryginalnego pytania dotycząca „właściwej kolejności” sugeruje, że z jakiegoś powodu potrzebujesz, aby kolejność była „poprawna” w bazie danych? To może popchnąć mnie do zajmowania się tam również drzewami.
źródło
Nie jest to dokładnie to samo, czego szukał pytający, ale miałem trudności z objęciem odpowiedzi udzielonych tutaj niejednoznacznie sformułowanych i nadal uważam, że ta odpowiedź pasuje do tytułu.
Moją odpowiedzią jest odwzorowanie płaskiej struktury na drzewo bezpośrednio na obiekcie, w którym wszystko, co masz, to znak
ParentID
na każdym obiekcie.ParentID
jestnull
lub0
jeśli jest to root. Naprzeciw pytającego zakładam, że wszystkie ważneParentID
punkty wskazują na coś innego na liście:źródło
oto implementacja ruby:
Kataloguje według nazwy atrybutu lub wyniku wywołania metody.
źródło
Zaakceptowana odpowiedź wydaje mi się zbyt złożona, więc dodaję jej wersje Ruby i NodeJS
Załóżmy, że lista węzłów płaskich ma następującą strukturę:
Funkcje, które zmienią płaską strukturę listy powyżej w drzewo, wyglądają następująco
dla Rubiego:
dla NodeJS:
źródło
null
undefined
null == undefined => true
w NodeJSjednym eleganckim sposobem na to jest przedstawienie pozycji na liście jako łańcucha zawierającego listę rodziców rozdzielonych kropkami, a na koniec wartość:
Podczas montażu drzewa otrzymujesz coś takiego:
Mam bibliotekę konfiguracji, która implementuje tę konfigurację zastąpienia (drzewo) z argumentów wiersza polecenia (lista). Algorytm dodawania pojedynczego elementu do listy do drzewa jest tutaj .
źródło
Czy utknąłeś, używając tylko tych atrybutów? Jeśli nie, fajnie byłoby utworzyć tablicę węzłów potomnych, w której można raz przejść przez wszystkie te obiekty, aby zbudować takie atrybuty. Stamtąd wybierz węzeł z dziećmi, ale bez rodziców i iteracyjnie utwórz drzewo od góry do dołu.
źródło
wersja java
źródło