二叉樹的三種遍歷非遞迴實現
阿新 • • 發佈:2018-12-25
1.二叉樹前序遍歷的非遞迴實現
* 實現思路,先序遍歷是要先訪問根節點,然後再去訪問左子樹以及右子樹,這明顯是遞迴定義,但這裡是用棧來實現的* 首先需要先從棧頂取出節點,然後訪問該節點,如果該節點不為空,則訪問該節點,同時把該節點的右子樹先入棧,然後
* 左子樹入棧。迴圈結束的條件是棧中不在有節點。即 !s.empty()
public void preOrder(Node root) { Stack<Node> s = new Stack<Node>(); s.push(root); Node p = null; while (!s.empty()) { p = s.pop(); if (p != null) { System.out.print(p.val+" "); s.push(p.right); s.push(p.left); } } }
2.二叉樹的中序遍歷非遞迴實現
* 實現思路,中序遍歷是要先遍歷左子樹,然後跟節點,最後遍歷右子樹。所以需要先把跟節點入棧然後在一直把左子樹入棧
* 直到左子樹為空,此時停止入棧。棧頂節點就是我們需要訪問的節點,取棧頂節點p並訪問。然後改節點可能有右子樹,所以
* 訪問完節點p後還要判斷p的右子樹是否為空,如果為空則接下來要訪問的節點在棧頂,所以將p賦值為null。如果不為空則
* 將p賦值為其右子樹的值。 迴圈結束的條件是p不為空或者棧不為空。
public void inOrder(Node root) { Stack<Node> s = new Stack<Node>(); Node p = root; do { while (p != null) { s.push(p); p = p.left; } p = s.pop(); System.out.print(p.val+" "); if (p.right != null) { p = p.right; } else p = null; } while(p != null || !s.empty()); }
3.二叉樹的後序遍歷裡非遞迴實現
* 實現思路,在進行後序遍歷的時候是先要遍歷左子樹,然後在遍歷右子樹,最後才遍歷根節點。所以在非遞迴的實現中要先把根節點入棧
* 然後再把左子樹入棧直到左子樹為空,此時停止入棧。此時棧頂就是需要訪問的元素,所以直接取出訪問p。在訪問結束後,還要判斷被訪
* 問的節點p是否為棧頂節點的左子樹,如果是的話那麼還需要訪問棧頂節點的右子樹,所以將棧頂節點的右子樹取出賦值給p。如果不是的
* 話則說明棧頂節點的右子樹已經訪問完了,那麼現在可以訪問棧頂節點了,所以此時將p賦值為null。判斷結束的條件是p不為空或者棧
* 不為空,若果兩個條件都不滿足的話,說明所有節點都已經訪問完成。
public void postOrder(Node root) {
Stack<Node> s = new Stack<Node>();
Node p = root;
while (p != null || !s.empty()) {
while(p != null) {
s.push(p);
p = p.left;
}
p = s.pop();
System.out.print(p.val+" ");
//這裡需要判斷一下,當前p是否為棧頂的左子樹,如果是的話那麼還需要先訪問右子樹才能訪問根節點
//如果已經是不是左子樹的話,那麼說明左右子書都已經訪問完畢,可以訪問根節點了,所以講p複製為NULL
//取根節點
if (!s.empty() && p == s.peek().left) {
p = s.peek().right;
}
else p = null;
}
}
最後附上節點的Java類程式碼
//樹的節點類
class Node {
public int val; //節點值
public Node left; //左子樹
public Node right; //右子樹
public Node() {}
public Node(int val, Node left, Node right) {
this.val = val;
this.left = left;
this.right = right;
}
}