1. 程式人生 > >二叉樹廣度優先遍歷和深度優先遍歷

二叉樹廣度優先遍歷和深度優先遍歷

二叉樹的遍歷方式:

1、深度優先:遞迴,非遞迴實現方式

  1)先序遍歷:先訪問根節點,再依次訪問左子樹和右子樹

  2)中序遍歷:先訪問左子樹,再訪問根節點嗎,最後訪問右子樹

  3)後序遍歷:先訪問左子樹,再訪問右子樹,最後訪問根節點

2、廣度優先

    按照樹的深度,一層一層的訪問樹的節點

package Solution;

import java.util.LinkedList;
import java.util.Queue;
import java.util.Stack;


public class BinaryTree {

    // 二叉樹節點
    public static class BinaryTreeNode {
        int value;
        BinaryTreeNode left;
        BinaryTreeNode right;

        public BinaryTreeNode(int value) {
            this.value = value;
        }

        public BinaryTreeNode(int value, BinaryTreeNode left,
                BinaryTreeNode right) {
            super();
            this.value = value;
            this.left = left;
            this.right = right;
        }

    }

    // 訪問樹的節點
    public static void visit(BinaryTreeNode node) {
        System.out.println(node.value);
    }

    /** 遞迴實現二叉樹的先序遍歷 */
    public static void preOrder(BinaryTreeNode node) {
        if (node != null) {
            visit(node);
            preOrder(node.left);
            preOrder(node.right);
        }
    }

    /** 遞迴實現二叉樹的中序遍歷 */
    public static void inOrder(BinaryTreeNode node) {
        if (node != null) {
            inOrder(node.left);
            visit(node);
            inOrder(node.right);
        }
    }

    /** 遞迴實現二叉樹的後序遍歷 */
    public static void postOrder(BinaryTreeNode node) {
        if (node != null) {
            postOrder(node.left);
            postOrder(node.right);
            visit(node);
        }
    }

    /** 非遞迴實現二叉樹的先序遍歷 */
    public static void iterativePreorder(BinaryTreeNode node) {
        Stack<BinaryTreeNode> stack = new Stack<>();
        if (node != null) {
            stack.push(node);
            while (!stack.empty()) {
                node = stack.pop();
                // 先訪問節點
                visit(node);
                // 把右子結點壓入棧
                if (node.right != null) {
                    stack.push(node.right);
                }
                // 把左子結點壓入棧
                if (node.left != null) {
                    stack.push(node.left);
                }
            }
        }
    }

    /** 非遞迴實現二叉樹的中序遍歷 */
    public static void iterativeInOrder(BinaryTreeNode root) {
        Stack<BinaryTreeNode> stack = new Stack<>();
        BinaryTreeNode node = root;
        while (node != null || stack.size() > 0) {
            // 把當前節點的所有左側子結點壓入棧
            while (node != null) {
                stack.push(node);
                node = node.left;
            }
            // 訪問節點,處理該節點的右子樹
            if (stack.size() > 0) {
                node = stack.pop();
                visit(node);
                node = node.right;
            }
        }
    }

    /** 非遞迴使用單棧實現二叉樹後序遍歷 */
    public static void iterativePostOrder(BinaryTreeNode root) {
        Stack<BinaryTreeNode> stack = new Stack<>();
        BinaryTreeNode node = root;
        // 訪問根節點時判斷其右子樹是夠被訪問過
        BinaryTreeNode preNode = null;
        while (node != null || stack.size() > 0) {
            // 把當前節點的左側節點全部入棧
            while (node != null) {
                stack.push(node);
                node = node.left;
            }
            if (stack.size() > 0) {
                BinaryTreeNode temp = stack.peek().right;
                // 一個根節點被訪問的前提是:無右子樹或右子樹已被訪問過
                if (temp == null || temp == preNode) {
                    node = stack.pop();
                    visit(node);
                    preNode = node;// 記錄剛被訪問過的節點
                    node = null;
                } else {
                    // 處理右子樹
                    node = temp;
                }
            }
        }
    }

    /** 非遞迴使用雙棧實現二叉樹後序遍歷 */
    public static void iterativePostOrderByTwoStacks(BinaryTreeNode root) {
        Stack<BinaryTreeNode> stack = new Stack<>();
        Stack<BinaryTreeNode> temp = new Stack<>();
        BinaryTreeNode node = root;
        while (node != null || stack.size() > 0) {
            // 把當前節點和其右側子結點推入棧
            while (node != null) {
                stack.push(node);
                temp.push(node);
                node = node.right;
            }
            // 處理棧頂節點的左子樹
            if (stack.size() > 0) {
                node = stack.pop();
                node = node.left;
            }
        }
        while (temp.size() > 0) {
            node = temp.pop();
            visit(node);
        }
    }

    /** 二叉樹廣度優先遍歷——層序遍歷 */
    public static void layerTraversal(BinaryTreeNode root) {
        Queue<BinaryTreeNode> queue = new LinkedList<>();

        if (root != null) {
            queue.add(root);
            while (!queue.isEmpty()) {
                BinaryTreeNode currentNode = queue.poll();
                visit(currentNode);
                if (currentNode.left != null) {
                    queue.add(currentNode.left);
                }

                if (currentNode.right != null) {
                    queue.add(currentNode.right);
                }

            }
        }
    }

    public static void main(String[] args) {

        // 構造二叉樹
        // 1
        // / \
        // 2 3
        // / / \
        // 4 5 7
        // \ /
        // 6 8
        BinaryTreeNode root = new BinaryTreeNode(1);
        BinaryTreeNode node2 = new BinaryTreeNode(2);
        BinaryTreeNode node3 = new BinaryTreeNode(3);
        BinaryTreeNode node4 = new BinaryTreeNode(4);
        BinaryTreeNode node5 = new BinaryTreeNode(5);
        BinaryTreeNode node6 = new BinaryTreeNode(6);
        BinaryTreeNode node7 = new BinaryTreeNode(7);
        BinaryTreeNode node8 = new BinaryTreeNode(8);

        root.left = node2;
        root.right = node3;
        node2.left = node4;
        node3.left = node5;
        node3.right = node7;
        node5.right = node6;
        node7.left = node8;
        System.out.println("二叉樹先序遍歷");
        preOrder(root);
        System.out.println("二叉樹先序遍歷非遞迴");
        iterativePreorder(root);
        System.out.println("二叉樹中序遍歷");
        inOrder(root);
        System.out.println("二叉樹中序遍歷非遞迴");
        iterativeInOrder(root);
        System.out.println("二叉樹後序遍歷");
        postOrder(root);
        System.out.println("二叉樹單棧非遞迴後序遍歷");
        iterativePostOrder(root);
        System.out.println("二叉樹雙棧非遞迴後序遍歷");
        iterativePostOrderByTwoStacks(root);
        System.out.println("二叉樹層樹序遍歷");
        layerTraversal(root);
    }
}