Jak mogę napisać iterator Java (tj potrzebuje next
i hasNext
metody), który zajmuje korzenia binarnego drzewa i iteracji węzłów drzewa binarnego w na zamówienie modę ?W zamówienie iterator do binarnego drzewa
Odpowiedz
Pierwszym elementem poddrzewa jest zawsze ten z lewej. Następny element po elemencie jest pierwszym elementem jego prawego poddrzewa. Jeśli element nie ma prawego elementu potomnego, następnym elementem jest pierwszy prawy przodek elementu. Jeśli element nie ma prawego dziecka ani prawego przodka, jest to element najbardziej prawy i jest ostatnim w iteracji.
Mam nadzieję, że mój kod jest czytelny dla człowieka i obejmuje wszystkie przypadki.
public class TreeIterator {
private Node next;
public TreeIterator(Node root) {
next = root;
if(next == null)
return;
while (next.left != null)
next = next.left;
}
public boolean hasNext(){
return next != null;
}
public Node next(){
if(!hasNext()) throw new NoSuchElementException();
Node r = next;
// If you can walk right, walk right, then fully left.
// otherwise, walk up until you come from left.
if(next.right != null) {
next = next.right;
while (next.left != null)
next = next.left;
return r;
}
while(true) {
if(next.parent == null) {
next = null;
return r;
}
if(next.parent.left == next) {
next = next.parent;
return r;
}
next = next.parent;
}
}
}
Rozważmy następujący drzewa:
d
/ \
b f
/\ /\
a c e g
- Pierwszym elementem jest „w pełni lewo od korzenia”
a
nie ma prawa dziecka, więc następnym elementem jest „up do momentu pojawienia się od lewej "b
ma prawo dziecko, więc iterowaćb
prawy poddrzewoc
nie ma właściwego dziecka. Jego rodzicem jestb
, który został przemierzony. Następny rodzic tod
, który nie został przejechany, więc zatrzymaj się tutaj.d
ma prawo poddrzewo. Jego lewym elementem jeste
.- ...
g
nie ma prawego poddrzewo, więc podejdź.f
został odwiedzony, ponieważ pochodzimy z prawej strony.d
został odwiedzony.d
nie ma rodzica, więc nie możemy przejść dalej. Przybyliśmy z prawego węzła i skończyliśmy iterować.
Był powód, dla którego nie umieściłem poprawnego iteratora w mojej odpowiedzi, i było tak, że OP musiałby to zrobić sam. Udzielanie takich odpowiedzi nikomu nie przynosi korzyści. –
@HunterMcMillen dobry punkt. No cóż, to i tak nie jest rzeczą kopiowania i wklejania. Przynajmniej jedna linia musi zostać zmieniona ;-), ale przyznaję, że nie była to celowa. Moim celem była czytelność, a nie poprawność. Nawet tego nie przetestowałem ;-) –
Uwielbiam twój pomysł, żeby go później przechowywać. Mógłbym myśleć tylko o tym, by przechowywać bieżący węzeł, a nie następny, i miałem kłopot z wymyśleniem sposobu na wydrukowanie pierwszego elementu. Dziękuję Ci. – Variadicism
Jest to dość proste, bo w prawidłowej kolejności przechodzenia odwiedzić lewy dziecko, jeśli istnieje, to węzeł główny, a następnie prawy dziecko:
visit_node(node)
if node.left: visit_node(node.left)
// visit the root node
if node.right: visit_node(node.right)
Diagram:
a
/ \ (in-order traversal would give bac)
b c
Ale pisząc iterator (na przykład iterator Java, który potrzebuje '' next' i metod hasNext'), jak można włączyć rekurencyjną metodę takiego? –
@PaulSeangwongree: Zawsze możesz uporządkować węzły i dodać je do innej kolekcji. –
Aby uzyskać następny wpis, "nextEntry()", dla iteratora, spojrzałem na fragmenty z java.util.TreeMap
wklejone poniżej. Mówiąc prostym językiem, powiedziałbym, że upewniasz się, że węzeł główny nie ma wartości null, a po pierwsze zwraca zero. Jeśli nie jest, przejrzyj prawy węzeł, jeśli nie jest pusty. Następnie odwiedź lewą stronę (jeśli nie jest pusta) i odwiedzaj ją wielokrotnie w pętli, aż naciśniesz zero. Jeśli pierwotny węzeł prawy ma wartość NULL, zamiast tego należy odwiedzić węzeł nadrzędny, jeśli nie jest to wartość NULL. Teraz wprowadź pętlę while, w której zobaczysz obiekt nadrzędny, aż uzyska on wartość zerową lub węzeł, który aktualnie odwiedzasz, ma swój prawy (podrzędny) węzeł równy ostatniej pozycji. Teraz zwróć dowolny wpis, na którym siedzisz. W przypadku niepowodzenia wszystkich tych opcji zwraca (oryginalny) węzeł główny. "HasNext()" sprawdza tylko, czy ten "następny wpis", który zwracasz, jest pusty lub nie.
public final boolean hasNext() {
return next != null;
}
final TreeMap.Entry<K,V> nextEntry() {
TreeMap.Entry<K,V> e = next;
if (e == null || e.key == fenceKey)
throw new NoSuchElementException();
if (m.modCount != expectedModCount)
throw new ConcurrentModificationException();
next = successor(e);
lastReturned = e;
return e;
}
static <K,V> TreeMap.Entry<K,V> successor(Entry<K,V> t) {
if (t == null)
return null;
else if (t.right != null) {
Entry<K,V> p = t.right;
while (p.left != null)
p = p.left;
return p;
} else {
Entry<K,V> p = t.parent;
Entry<K,V> ch = t;
while (p != null && ch == p.right) {
ch = p;
p = p.parent;
}
return p;
}
}
Tak, zrobiłem. Opublikuj swoje i może to być zaakceptowana odpowiedź, jeśli będzie równa lub większa od mojego wyjaśnienia. W pliku TreeMap.java dołączonym do pakietu jdk stwierdza on, że kod jest prawidłowy. Jeśli tak jest, powiem, że ~ 30 linii na 2400 jest dozwolonym użytkiem do celów edukacyjnych. – apcris
Opublikowałem swoją odpowiedź. –
Nie wiesz transkrypcja pomaga zrozumieć ... –
- 1. Implementacja drzewa binarnego drzewa javascript
- 2. instancji Monada do binarnego drzewa
- 3. Algorytm wstawiania drzewa binarnego
- 4. Destruktor drzewa wyszukiwania binarnego
- 5. Dlaczego drzewa wyszukiwania binarnego?
- 6. drzewa wyszukiwania binarnego w rubinach
- 7. Włóż posortowaną tablicę do drzewa wyszukiwania binarnego
- 8. Aby wydrukować granicę drzewa binarnego
- 9. Wdrażanie zrównoważonego drzewa wyszukiwania binarnego?
- 10. Zrozumienie budowy drzewa wyszukiwania binarnego
- 11. Budowanie zrównoważonego drzewa wyszukiwania binarnego
- 12. Tworzenie drzewa binarnego w Javie do celów programowania genetycznego
- 13. C++: Suma wartości wszystkich węzłów drzewa binarnego
- 14. Usuń rekursywnie z drzewa wyszukiwania binarnego
- 15. Implementacja drzewa binarnego przy użyciu Swift enum
- 16. Jak działa iterator std :: map?
- 17. kolejność drukowania w kolejności drzewa binarnego w sposób Zygzak
- 18. Przejazd przez wszystkich węzłach binarnego drzewa w Javie
- 19. Jak działa Iterator w zestawie
- 20. Czy istnieje implementacja drzewa wyszukiwania binarnego w .NET 4?
- 21. Poszukiwane: Nawrót Formuła In-Order drzewa binarnego sposobu wyjścia
- 22. Potrzebna pomoc Tworzenie drzewa binarnego z tabelą prawdy
- 23. XobotOS: Dlaczego benchmark drzewa binarnego C# używa struktury struct?
- 24. iterator C++ do const_iterator
- 25. Konwersja Wyliczanie do iterator
- 26. C++ iterator i reverse iterator
- 27. Jak zrobić drzewo wyszukiwania binarnego w Clojure?
- 28. Więcej konwersji Python do binarnego?
- 29. "Generic" iterator w C++
- 30. Łańcuch do wyjścia binarnego w Javie
Myślę, że pytanie jest wystarczająco jasne, jeśli wiesz, czym jest drzewo binarne i czy masz doświadczenie z analizowaniem. – ilomambo
Myślę, że to jest prawdziwe pytanie. Prawdopodobnie zostałby zamknięty jako zbyt szeroki. –