【二叉樹的遍歷-2】中序遍歷(遞歸與非遞歸)
【二叉樹的遍歷-3】後序遍歷(遞歸與非遞歸)
【二叉樹的遍歷-4】層序遍歷
本篇主要是二叉樹的遍歷的簡介和前序遍歷的代碼實現,另外幾種遍歷方式見上面鏈接
二叉樹的遍歷
關於二叉樹的遍歷,百度百科是這樣說的:
所謂遍歷(Traversal)是指沿着某條搜索路線,依次對樹中每個結點均做一次且僅做一次訪問。訪問結點所做的操作依賴於具體的應用問 題。 遍歷是二叉樹上最重要的運算之一,是二叉樹上進行其它運算之基礎。
遍歷方式主要有四種:
1.前序遍歷:根結點 --> 左子樹 --> 右子樹
2.中序遍歷:左子樹–> 根結點 --> 右子樹
3.後序遍歷:左子樹–> 右子樹 --> 根結點
4.層序遍歷:從上到下,從左到右一層一層的遍歷
前面三種其實很好記,可以想象成只是把根的訪問次序移了一下。
看一個具體的實例:
前序遍歷結果:A BDEH CFG
中序遍歷結果:DBEH A FCG
後序遍歷結果:DHEB FGC A
層序遍歷結果:A BC DEFG H
前序遍歷代碼實現
前序遍歷(DLR),也叫做先根遍歷、先序遍歷、前序周遊,遍歷次序可記做根左右。首先訪問根結點然後遍歷左子樹,最後遍歷右子樹。
記住一點:根結點 --> 左子樹 --> 右子樹
遞歸方式:
對於遞歸過程我們其實不需要太在意,主要是要想清楚讓計算機幹什麼。計算機都可能溢出,用人腦去遍歷就更不太可能了。
比如這個先序遍歷,我們要先打印頭節點對吧?那我打印完了頭節點,然後再打印左節點,再打印右節點。然後我們就只用告訴計算機我想先打印當前節點,再打印左邊結點,之後再打印右邊結點就可以了。
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class BinaryTree {
public void preorderTraversal(TreeNode root) {
if(root != null) {
System.out.println(root.val); //每次遍歷都打印當前節點,然後再去打印左右子樹節點,至於左右子樹再怎麼向下遞歸打印我們就不care了
preorderTraversal(root.left); //遞歸調用,遍歷左子樹,打印左子樹的節點
preorderTraversal(root.right); //遞歸調用遍歷右子樹,打印左子樹節點
}
}
}
非遞歸方式:
迭代解法本質上也是在模擬遞歸,因爲在遞歸的過程中使用了系統棧,所以在迭代的解法中常用Stack來模擬系統棧。
具體思路:
1.先創建一個Stack用來存放節點;
2.由於前序遍歷先打印根節點,所以先將根節點入棧,然後打印;
3.然後由於我們想先打印左子樹節點,然後右子樹節點。根據棧先入後出的特性,先加入棧的就應該是右子樹,然後左子樹。
代碼如下:
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class BinaryTree {
public void preorderTraversal(TreeNode root) {
if(root == null) { //空樹直接返回,就不用遍歷了
return;
}
Stack<TreeNode> s = new Stack<>();
s.push(root); //根節點入棧
while(!s.empty()) { //循環條件:棧不爲空,因爲棧不爲空說明每遍歷完
TreeNode cur = s.pop(); //此時棧頂保存的就是根節點,由於前序遍歷先打印根節點,所以先將根節點出棧,
System.out.println(cur.val); //打印根節點
//由於棧先進後出特性,所以想先打印左子樹節點,就將右子樹節點先入棧
if(cur.right != null) {
s.push(cur.right);
}
if(cur.left != null) {
s.push(cur.left);
}
}
}
}
附leetcode前序非遞歸遍歷代碼
代碼如下:
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
public List<Integer> preorderTraversal(TreeNode root) {
List<Integer> ret = new ArrayList<>();
if(root == null) {
return ret;
}
Stack<TreeNode> s = new Stack<>();
s.push(root);
while(!s.empty()) {
TreeNode cur = s.pop();
ret.add(cur.val);
if(cur.right != null) {
s.push(cur.right);
}
if(cur.left != null) {
s.push(cur.left);
}
}
return ret;
}
}