二叉樹三種遍歷遞迴及非遞迴實現
阿新 • • 發佈:2019-01-29
二叉樹的三種遍歷方式包括:
- 前序遍歷
- 中序遍歷
- 後序遍歷
三種遍歷的遞迴方法都非常好實現,而且簡單易懂。非遞迴實現也是通過使用棧來模擬遍歷的過程。順便提一句,能用遞迴做的,基本都能用棧來實現。前序遍歷和中序遍歷的非遞迴寫法相對比較簡單,只需要模擬遍歷過程即可。後序遍歷非遞迴寫法比較難,需要藉助一個輔助指標來記錄右子樹是否訪問過,以防止重複訪問陷入死迴圈。下面分別給出三種遍歷方法的遞迴和非遞迴實現的程式碼:
前序遍歷
遞迴:
public void PreOrderTraversal(TreeNode root) { if (root == null) { return; } System.out.print(root.val); if (root.left != null) { PreOrderTraversal(root.left); } if (root.right != null) { PreOrderTraversal(root.right); } }
非遞迴:
public void PreOrderTraversal2(TreeNode root){ Stack<TreeNode> stack = new Stack<>(); TreeNode node; if (root == null) { return; } stack.push(root); while (!stack.empty()) { node = stack.pop(); System.out.print(node.val); if (node.right != null) { stack.push(node.right); } if (node.left != null) { stack.push(node.left); }//end if } }
將根節點放入棧中,當棧不空時,取出棧頂元素x,訪問x的值,如果x的左孩子不為空,將其左孩子入棧;如果其右孩子不為空,將其右孩子入棧,直至棧空。
中序遍歷
遞迴:
public void InOrderTraversal(TreeNode root) { if (root == null) { return; } if (root.left != null) { InOrderTraversal(root.left); } System.out.print(root.val); if (root.right != null) { InOrderTraversal(root.right); } }
非遞迴:
public void InOrderTraversal2(TreeNode root) {
if (root == null) {
return;
}
TreeNode node;
Stack<TreeNode> stack = new Stack<>();
stack.push(root);
node = root.left;
while ((node != null)||(!stack.empty())) {
while (node != null) {
stack.push(node);
node = node.left;
}
node = stack.pop();
System.out.print(node.val);
node = node.right;
}
}
1、先遍歷到二叉樹的最左結點
2、彈出棧頂元素x並訪問
3、考察x的右子樹是否為空,如果為空則執行2,否則將當前結點設為x的右子樹並執行1.
後序遍歷
遞迴:
public void PostOrderTraversal(TreeNode root) {
if (root == null) {
return;
}
if (root.left != null) {
PostOrderTraversal(root.left);
}
if (root.right != null) {
PostOrderTraversal(root.right);
}
System.out.print(root.val);
}
非遞迴:
public void PostOrderTraversal2(TreeNode root) {
if (root == null) {
return;
}
Stack<TreeNode> stack = new Stack<>();
stack.push(root);
TreeNode node = root.left;
TreeNode lastVisit = null;
while (node != null) {
stack.push(node);
node = node.left;
}
while (!stack.empty()) {
node = stack.pop();
if (node.right == null || node.right == lastVisit) {
System.out.print(node.val);
lastVisit = node;
} else {
stack.push(node);
node = node.right;
while (node != null) {
stack.push(node);
node = node.left;
}
}
}
}
後序遍歷非遞迴做法需要設定一個指標lastVisit指向上次輸出的元素。
1、從根節點開始遍歷到最左節點
2、當棧不空時彈出棧頂元素
3、如果棧頂元素x的右子樹為空或者x的右子樹等於lastVisit說明該右子樹已經訪問過,訪問當前節點x並將lastVisit指向x。
否則將x壓回棧中,並且將當前節點指向x的右子樹,執行步驟1.