二叉樹的遍歷


二叉樹的遍歷分為兩大類:

1、深度優先遍歷(前序遍歷、中序遍歷、后序遍歷)

2、廣度優先遍歷

 

         3

    2             8

9    10     null        4

package xiaohui;

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

/**
 * @author 忠哥
 * @create 2021-10-24
 **/
public class CreateBinaryTreeByLinkedList {
    /**
     * 構建二叉樹
     *
     * @param linkedList 鏈表
     * @return
     */
    public static TreeNode createTreeNode(LinkedList<Integer> linkedList) {
        TreeNode node = null;
        if (linkedList == null || linkedList.isEmpty()) {
            return null;
        }
        //從鏈表中移除第一個並將其返回
        Integer data = linkedList.removeFirst();
        //如果元素為空,則不再遞歸
        if (data != null) {
            node = new TreeNode(data);
            node.left = createTreeNode(linkedList);
            node.right = createTreeNode(linkedList);
        }
        return node;
    }

    /**
     * 前序遍歷
     *
     * @param node
     */
    public static void preOut(TreeNode node) {
        if (node == null) {
            return;
        }
        System.out.print(node.data + "\t");
        preOut(node.left);
        preOut(node.right);
    }

    /**
     * 借助棧實現 前序遍歷
     *
     * @param root
     */
    public static void preOutStack(TreeNode root) {
        TreeNode treeNode = root;
        Stack<TreeNode> stack = new Stack<>();
        while (treeNode != null || !stack.isEmpty()) {
            while (treeNode != null) {
                System.out.print(treeNode.data + "\t");
                stack.push(treeNode);
                treeNode = treeNode.left;
            }
            if (!stack.isEmpty()) {
                treeNode = stack.pop();
                treeNode = treeNode.right;
            }
        }
    }

    /**
     * 用非遞歸的方式實現二叉樹的先序遍歷(LeetCode144):
     * 1、申請一個棧stack,然后將頭節點壓入stack中。
     * 2、從stack中彈出棧頂節點,打印,再將其右孩子節點(不為空的話)先壓入stack中,最后將其左孩子節點(不為空的話)壓入stack中。
     * 3、不斷重復步驟2,直到stack為空,全部過程結束。
     *
     * @param root
     */
    private static void doPreOutStack(TreeNode root) {
        Stack<TreeNode> stack = new Stack<>();
        if (root != null) {
            stack.push(root);
            while (!stack.empty()) {
                TreeNode node = stack.pop();
                System.out.print(node.data + "\t");
                if (node.right != null) {
                    stack.push(node.right);
                }
                if (node.left != null) {
                    stack.push(node.left);
                }
            }
        }
    }

    /**
     * 中序遍歷
     *
     * @param node
     */
    public static void midOut(TreeNode node) {
        if (node == null) {
            return;
        }
        midOut(node.left);
        System.out.print(node.data + "\t");
        midOut(node.right);
    }

    /**
     * 用非遞歸的方式實現二叉樹的中序遍歷(LeetCode94):
     * 1、申請一個棧stack,初始時令cur=head
     * 2、先把cur壓入棧中,依次把左邊界壓入棧中,即不停的令cur=cur.left,重復步驟2
     * 3、不斷重復2,直到為null,從stack中彈出一個節點,記為node,打印node的值,並令cur=node.right,重復步驟2
     * 4、當stack為空且cur為空時,整個過程停止。
     *
     * @param root
     */
    private static void doMidOutStack(TreeNode root) {
        Stack<TreeNode> stack = new Stack<>();
        if (root != null) {
            while (root != null || !stack.isEmpty()) {
                if (root != null) {
                    stack.push(root);
                    root = root.left;
                } else {
                    root = stack.pop();
                    System.out.print(root.data + "\t");
                    root = root.right;
                }

            }
        }
    }

    /**
     * 后序遍歷
     *
     * @param node
     */
    public static void lastOut(TreeNode node) {
        if (node == null) {
            return;
        }
        lastOut(node.left);
        lastOut(node.right);
        System.out.print(node.data + "\t");
    }

    /**
     * 用非遞歸的方式實現二叉樹的后序遍歷(LeetCode145):
     * 用非遞歸的方式實現后序遍歷有點麻煩。
     * 1、申請一個棧s1,然后將頭節點壓入棧s1中。
     * 2、從s1中彈出的節點記為cur,然后依次將cur的左孩子節點和右孩子節點壓入s1中。
     * 3、在整個過程中,每一個從s1中彈出的節點都放進s2中。
     * 4、不斷重復步驟2和步驟3,直到s1為空,過程停止。
     * 5、從s2中依次彈出節點並打印,打印的順序就是后序遍歷的順序。
     *
     * @param root
     */
    private static void doLastOutStack(TreeNode root) {
        Stack<TreeNode> stack1 = new Stack<>();
        Stack<TreeNode> stack2 = new Stack<>();
        if (root != null) {
            stack1.push(root);
            while (!stack1.isEmpty()) {
                root = stack1.pop();
                stack2.push(root);
                if (root.left != null) {
                    stack1.push(root.left);
                }
                if (root.right != null) {
                    stack1.push(root.right);
                }
            }
            while (!stack2.isEmpty()) {
                System.out.print(stack2.pop().data + "\t");
            }
        }
    }

    /**
     * 二叉樹廣度優先遍歷(層序遍歷)
     *
     * @param root
     */
    private static void levelOrderTraversal(TreeNode root) {
        Queue<TreeNode> queue = new LinkedList<>();
        queue.offer(root);
        while (!queue.isEmpty()) {
            TreeNode node = queue.poll();
            System.out.print(node.data + "\t");
            if (node.left != null) {
                queue.offer(node.left);
            }
            if (node.right != null) {
                queue.offer(node.right);
            }
        }
    }


    public static void main(String[] args) {
        LinkedList linkedList = new LinkedList<Integer>(Arrays.asList(new Integer[]{3, 2, 9, null, null, 10, null, null, 8, null, 4}));
        TreeNode node = createTreeNode(linkedList);
        System.out.println("前序遍歷...");
        preOut(node);
        System.out.println();

        System.out.println("借助棧實現前序遍歷01...");
        preOutStack(node);
        System.out.println();

        System.out.println("借助棧實現前序遍歷02...");
        doPreOutStack(node);
        System.out.println();

        System.out.println("中序遍歷...");
        midOut(node);
        System.out.println();

        System.out.println("中序遍歷Stack...");
        doMidOutStack(node);
        System.out.println();


        System.out.println("后序遍歷...");
        lastOut(node);
        System.out.println();

        System.out.println("后序遍歷Stack...");
        doLastOutStack(node);
        System.out.println();

        System.out.println("廣度優先遍歷...");
        levelOrderTraversal(node);
    }

}

執行結果如下:

前序遍歷...
3 2 9 10 8 4
借助棧實現前序遍歷01...
3 2 9 10 8 4
借助棧實現前序遍歷02...
3 2 9 10 8 4
中序遍歷...
9 2 10 3 8 4
中序遍歷Stack...
9 2 10 3 8 4
后序遍歷...
9 10 2 4 8 3
后序遍歷Stack...
9 10 2 4 8 3
廣度優先遍歷...
3 2 8 9 10 4


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM