數據結構與算法-二叉樹前序、中序、后序、層序遍歷

二叉樹是每個節點最多只有兩個分支(即不存在分支度大于2的節點)的樹結構。通常分支被稱作“左子樹”或“右子樹”。二叉樹的分支具有左右次序,不能隨意顛倒。

序言

二叉樹的遍歷方式主要有:先序遍歷、中序遍歷、后序遍歷、層次遍歷。先序、中序、后序指的是父節點被訪問的次序。本篇文章將用java代碼實現下圖中的二叉樹的遍歷


數據結構 二叉樹

創建圖中節點

public class TreeNode<T> {
    private T data;
    private TreeNode left;
    private TreeNode right;
}
TreeNode treeNodeA = new TreeNode("A");
TreeNode treeNodeB = new TreeNode("B");
TreeNode treeNodeC = new TreeNode("C");
TreeNode treeNodeD = new TreeNode("D");
TreeNode treeNodeE = new TreeNode("E");
TreeNode treeNodeF = new TreeNode("F");
        
treeNodeA.setLeft(treeNodeB);
treeNodeA.setRight(treeNodeC);

treeNodeB.setLeft(treeNodeD);
treeNodeB.setRight(treeNodeE);

treeNodeC.setLeft(treeNodeF);

前序遍歷

遍歷思路:在遍歷過程中,父節點先于它的子節點被訪問(父節點 -> 左子樹 -> 右子樹)

  • 前序遍歷代碼
    private void preOrderTraverse(TreeNode treeNode, VisitListener visitListener) {
        if (treeNode == null) {
            return;
        }
        visitListener.visit(treeNode.getData());
        preOrderTraverse(treeNode.getLeft(), visitListener);
        preOrderTraverse(treeNode.getRight(), visitListener);
    }
  • 測試代碼
        preOrderTraverse(treeNodeA, new VisitListener<String>() {
            @Override
            public void visit(String treeNodeData) {
                Log.d("TAG", treeNodeData);
            }
        });
  • 輸出
2020-05-25 21:32:40.508 16157-16157/? D/TAG: A
2020-05-25 21:32:40.508 16157-16157/? D/TAG: B
2020-05-25 21:32:40.508 16157-16157/? D/TAG: D
2020-05-25 21:32:40.508 16157-16157/? D/TAG: E
2020-05-25 21:32:40.508 16157-16157/? D/TAG: C
2020-05-25 21:32:40.508 16157-16157/? D/TAG: F

中序遍歷

遍歷思路:在遍歷過程中,父節點被訪問的次序位于左右子節點之間( 左子樹 -> 父節點 ->右子樹)

  • 中序遍歷代碼
    private void infixOrderTraverse(TreeNode treeNode, VisitListener visitListener) {
        if (treeNode == null) {
            return;
        }
        infixOrderTraverse(treeNode.getLeft(), visitListener);
        visitListener.visit(treeNode.getData());
        infixOrderTraverse(treeNode.getRight(), visitListener);
    }
  • 測試代碼
        infixOrderTraverse(treeNodeA, new VisitListener<String>() {
            @Override
            public void visit(String treeNodeData) {
                Log.d("TAG", treeNodeData);
            }
        });
  • 輸出
2020-05-25 21:32:40.508 16157-16157/? D/TAG: D
2020-05-25 21:32:40.508 16157-16157/? D/TAG: B
2020-05-25 21:32:40.508 16157-16157/? D/TAG: E
2020-05-25 21:32:40.508 16157-16157/? D/TAG: A
2020-05-25 21:32:40.508 16157-16157/? D/TAG: F
2020-05-25 21:32:40.508 16157-16157/? D/TAG: C

后序遍歷

遍歷思路:在遍歷過程中,訪問完左右子節點之后再訪問父節點( 左子樹 ->右子樹 -> 父節點)

  • 后序遍歷代碼
    private void epilogueOrderTraverse(TreeNode treeNode, VisitListener visitListener) {
        if (treeNode == null) {
            return;
        }
        epilogueOrderTraverse(treeNode.getLeft(), visitListener);
        epilogueOrderTraverse(treeNode.getRight(), visitListener);
        visitListener.visit(treeNode.getData());
    }
  • 測試代碼
        epilogueOrderTraverse(treeNodeA, new VisitListener<String>() {
            @Override
            public void visit(String treeNodeData) {
                Log.d("TAG", treeNodeData);
            }
        });
  • 輸出
2020-05-25 21:32:40.508 16157-16157/? D/TAG: D
2020-05-25 21:32:40.508 16157-16157/? D/TAG: E
2020-05-25 21:32:40.508 16157-16157/? D/TAG: B
2020-05-25 21:32:40.508 16157-16157/? D/TAG: F
2020-05-25 21:32:40.508 16157-16157/? D/TAG: C
2020-05-25 21:32:40.508 16157-16157/? D/TAG: A

層序遍歷

遍歷思路:在遍歷過程中,按照從上到下、從左向右的順序訪問二叉樹的每個節點

  • 層序遍歷代碼
    private void levelOrderTraverse(TreeNode treeNode, VisitListener visitListener) {
        if (treeNode == null) {
            return;
        }
        Queue<TreeNode> treeNodeQueue = new ArrayDeque<>();
        treeNodeQueue.add(treeNode);
        TreeNode currentNode;
        while (!treeNodeQueue.isEmpty()) {
            currentNode = treeNodeQueue.peek();
            visitListener.visit(currentNode.getData());
            if (currentNode.getLeft() != null) {
                treeNodeQueue.add(currentNode.getLeft());
            }
            if (currentNode.getRight() != null) {
                treeNodeQueue.add(currentNode.getRight());
            }
            treeNodeQueue.poll();
        }
    }
  • 測試代碼
        levelOrderTraverse(treeNodeA, new VisitListener<String>() {
            @Override
            public void visit(String treeNodeData) {
                Log.d("TAG", treeNodeData);
            }
        });
  • 輸出
2020-05-25 21:32:40.508 16157-16157/? D/TAG: A
2020-05-25 21:32:40.508 16157-16157/? D/TAG: B
2020-05-25 21:32:40.508 16157-16157/? D/TAG: C
2020-05-25 21:32:40.508 16157-16157/? D/TAG: D
2020-05-25 21:32:40.508 16157-16157/? D/TAG: E
2020-05-25 21:32:40.508 16157-16157/? D/TAG: F
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。