遍歷是數據結構中的常見操作,就是把所有的元素遍歷一遍。
線性結構的遍歷無非是兩種,正序遍歷和逆序遍歷,也就是從頭依次遍歷或者從尾依次遍歷。
二叉樹的遍歷方式有 4 種,是根據不同的節點訪問順序來區分:
遍歷方法 | 訪問順序 | 備注 |
---|---|---|
前序遍歷(Preorder Traversal) | 根節點、左子樹、右子樹 | |
中序遍歷(Inorder Traversal) | 左子樹、根節點、右子樹 | |
后序遍歷(Postorder Traversal) | 左子樹、右子樹、根節點 | |
層序遍歷(Level Order Traversal) | 從上到下、從左到右依次訪問每一個節點 |
從上面表格中可以大致總結出前三種遍歷的唯一區別就是訪問的順序不同,那么就可以都使用遞歸的方式實現。
凡是使用遞歸方式,必須要確定一個結束遞歸的條件,因為二叉樹的遍歷都是從根節點開始,直到所有節點都遍歷完成,所以結束遞歸的條件就是節點為 null。
// 結束遞歸條件
if (node == null) return;
前序遍歷
前序遍歷的順序是根節點、左子樹,最后右子樹
/**
* 前序遍歷(遞歸)
*/
public void preorderTanversal() {
preorderTanversal(root, visitor);
}
private void preorderTanversal(Node<E> node) {
// 結束條件
if (node == null) return;
// 訪問根節點
System.out.println(node.element);
// 訪問左子樹
preorderTanversal(node.left, visitor);
// 訪問右子樹
preorderTanversal(node.right, visitor);
}
中序遍歷
中序遍歷的順序是左子樹、根節點,最后右子樹
/**
* 中序遍歷(遞歸)
*/
public void inorderTraversal() {
preorderTanversal(root, visitor);
}
private void inorderTraversal(Node<E> node) {
// 結束條件
if (node == null) return;
// 訪問左子樹
inorderTraversal(node.left, visitor);
// 訪問根節點
System.out.println(node.element);
// 訪問右子樹
inorderTraversal(node.right, visitor);
}
特別:中序遍歷是只要保證根節點是在中間訪問,那么先訪問左子樹還是先訪問右子樹,根據心情來決定就好。
后序遍歷
后序遍歷的順序是左子樹、右子樹,最后是根節點:
/**
* 后序遍歷(遞歸)
*/
public void postorderTraversal() {
preorderTanversal(root, visitor);
}
private void postorderTraversal(Node<E> node) {
// 結束條件
if (node == null) return;
// 訪問左子樹
postorderTraversal(node.left, visitor);
// 訪問右子樹
postorderTraversal(node.right, visitor);
// 訪問根節點
System.out.println(node.element);
}
層序遍歷
層序遍歷的訪問順序是從左到右,從上到下依次遍歷。那么就可以通過隊列的方式去實現,在遍歷每一個節點的同時(出隊操作),將它的左右子節點依次入隊,直到隊列中的元素為空,則遍歷就結束了。
/**
* 層序遍歷
*/
public void leverOrderTraversal() {
if (root == null) return;
// 創建隊列
Queue<Node<E>> queue = new LinkedList<>();
// 第一節點入隊
queue.offer(root);
while (!queue.isEmpty()) {
// 處理事件
Node<E> node = queue.poll();
System.out.println(node.element);
// 依次將存在的左右子樹入隊
if (node.left != null) {
queue.offer(node.left);
}
if (node.right != null) {
queue.offer(node.right);
}
}
}
擴展
使用遞歸方式實現二叉樹的遍歷在代碼實現上是簡單的,關鍵要明白遞歸的思想和思路。建議在紙上去親自演算一下遞歸方式,會有利於理解。