二叉树的遍历

二叉树的遍历分为两大类:

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 + "	");
        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 + "	");
                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 + "	");
                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 + "	");
        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 + "	");
                    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 + "	");
    }

    /**
     * 用非递归的方式实现二叉树的后序遍历(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 + "	");
            }
        }
    }

    /**
     * 二叉树广度优先遍历(层序遍历)
     *
     * @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 + "	");
            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

原文地址:https://www.cnblogs.com/huangzhen22/p/15468118.html