我該如何編寫一個Java迭代器(即需要next
和hasNext
方法),它取一棵二叉樹的根並遍歷二叉樹的節點有序時尚?二叉樹的有序迭代器
回答
子樹的第一個元素始終是最左邊的元素。元素之後的下一個元素是其右側子樹的第一個元素。如果元素沒有右側子元素,則下一個元素是元素的第一個右側祖先。如果元素既沒有正確的孩子也沒有正確的祖先,它是最右邊的元素,它是迭代中的最後一個元素。
我希望我的代碼是人類可讀的,涵蓋所有情況。
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;
}
}
}
考慮下面的樹:
d
/ \
b f
/\ /\
a c e g
- 的第一個元素是
a
沒有一個合適的孩子「完全從根左」,所以下一個元素是「漲直到你從左邊「b
確實有一個正確的孩子,所以迭代b
的右子樹c
沒有合適的孩子。它的父母是b
,已被遍歷。下一位父母是d
,它尚未遍歷,所以請到此處。d
有一個右子樹。其最左邊的元素是e
。- ...
g
沒有正確的子樹,所以走了。f
已被訪問,因爲我們來自右邊。d
已被訪問。d
沒有父母,所以我們不能再向上移動。我們來自最右邊的節點,我們完成迭代。
有一個原因,我沒有在我的答案中發佈一個有效的迭代器,並且它是這樣,OP將不得不自己做。給出這樣的答案對任何人都沒有好處。 –
@HunterMcMillen好點。但是,這不是一個複製和粘貼的東西。至少有一行必須改變;-)但我承認這不是故意的。我的重點是可讀性,而不是正確性。我甚至沒有測試它;-) –
我愛你的想法下一個存儲。我只能想到存儲當前的節點,而不是下一個節點,而且我有很多麻煩提出了打印第一個元素的方法。謝謝。 – Variadicism
這是非常簡單的,對於中序遍歷您訪問的左孩子如果有,那麼根節點,然後右子:
visit_node(node)
if node.left: visit_node(node.left)
// visit the root node
if node.right: visit_node(node.right)
圖:
a
/ \ (in-order traversal would give bac)
b c
但是,當編寫一個迭代器(例如需要'next'和'hasNext'方法的Java迭代器)時,如何合併這樣的遞歸方法? –
@PaulSeangwongree:您始終可以按順序獲取節點並將它們添加到其他集合中。 –
爲了得到下一個條目,nextEntry(),對於迭代器,我查看了下面粘貼的java.util.TreeMap
的片段。用簡單的英語,我會說你確保根節點不是null,否則返回null。如果不是,則如果它不爲空,則向右移動正確的節點。然後訪問左邊(如果不爲null)並在while循環中重複訪問該左邊的內容,直到達到null。如果原始權利節點爲空,那麼代替所有這些,請訪問父節點,如果它不爲空。現在輸入一個while循環,在這個循環中,你可以瀏覽父節點,直到它爲null,或者你正在訪問的節點的右邊(子節點)節點等於你的最後一個位置。現在返回您所坐的任何條目。如果所有這些選項失敗,則返回(原始)根節點。 'HasNext()'僅僅檢查你所返回的這個「下一個條目」是否爲null。
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;
}
}
是的,我做到了。請發佈你的,如果我的解釋相同或更好,可能會被接受。它實際上在與JDK打包的TreeMap.java文件中聲明代碼是正確的。如果是這樣的話,我會說在2400條線中約有30條線用於教育目的。 – apcris
我確實發佈了我的答案。 –
不確定轉錄有助於理解... –
- 1. 二叉樹:有序迭代器:Java
- 2. 二叉樹:迭代序列打印
- 3. 迭代器模板二叉樹
- 4. 二叉搜索樹inorder迭代器C++
- 5. C#中的二叉樹迭代#
- 6. 二叉樹搜索的迭代版本
- 7. 迭代二叉樹橫向問題
- 8. 迭代插入到二叉樹
- 9. C++迭代銷燬二叉樹
- 10. 二叉樹後序遍歷的迭代過程
- 11. 爲什麼我的二叉樹迭代器停止了?
- 12. C++,實現二叉樹的自定義迭代器(長)
- 13. Python:二叉樹遍歷迭代器不使用條件
- 14. 在二叉搜索樹中實現迭代器
- 15. 序言,二叉樹
- 16. 迭代八叉樹遍歷
- 17. 二叉樹的C++程序
- 18. 二叉樹的有序繼任者
- 19. 有序的二叉樹插入
- 20. 二叉樹代碼錯誤
- 21. 二叉樹 - 哪一種二叉樹
- 22. 二叉樹到二叉搜索樹(BST)
- 23. 的java:執行二叉搜索樹和覆蓋迭代
- 24. 迭代通過二叉搜索樹的java
- 25. 插入二叉樹的一個節點 - 轉換迭代遞歸
- 26. 遞歸算法的迭代版本,以二叉樹
- 27. C中的非遞歸/迭代二叉搜索樹(作業)
- 28. 需要幫助二叉樹程序(非二叉搜索樹)
- 29. 代表免費樹到二叉樹
- 30. 有序二叉樹字符串
我認爲這個問題很清楚,如果你知道二叉樹是什麼,並且有解析它們的經驗。 – ilomambo
我認爲這是真正的問題。它應該可能被封閉得太寬了。 –