算法通关村第7关——迭代实现二叉树的前中后序遍历

158 阅读2分钟

利用非递归的方式实现前中后序遍历

前序遍历的图解:

image.png

image.png

image.png

image.png

image.png

image.png

前序遍历理解了,那么中序后序遍历也要画画图,也就能很快的理解与记忆了; 不过后序遍历的实现还是有点难度的,后面会补上图解

前中后序的非递归代码实现如下:

import java.util.ArrayList;
import java.util.List;
import java.util.Stack;

/**
 * 利用非递归的方法实现二叉树的前,中,后序遍历
 */
public class UnRecursiveTraversalBT_Coding {

    // 1.利用栈来实现先序遍历
    public static List<Integer> preOrder(TreeNode root) {
        if (root == null) {
            return new ArrayList<>();
        }
        // 作为返回前序序列的集合
        List<Integer> resList = new ArrayList<>();
        // 定义一个栈
        Stack<TreeNode> stack = new Stack<>();
        // 先把根节点放入栈中
        stack.push(root);
        TreeNode cur;
        while (!stack.isEmpty()) {
            // 节点出栈即可添加到集合中
            cur = stack.pop();
            resList.add(cur.val);
            // 先放右子树的节点,再放左子树的节点(想想栈的特性——后进先出)最后出栈的顺序一定是先左再右
            if (cur.right != null) {
                stack.push(cur.right);
            }
            if (cur.left != null) {
                stack.push(cur.left);
            }
        }
        return resList;
    }

    // 2.利用栈的方式来实现中序遍历过程
    public static List<Integer> inOrder(TreeNode root) {
        if (root == null) {
            return new ArrayList<>();
        }
        List<Integer> resList = new ArrayList<>();
        Stack<TreeNode> stack = new Stack<>();
        // 先把整棵树的最左边部分放入栈中
        while (root != null) {
            stack.push(root);
            root = root.left;
        }
        // 判断栈不为空
        while (!stack.isEmpty()) {
            // 让栈中元素出栈,此时的栈顶元素一定是最左节点
            root = stack.pop();
            // 在集合中添加当前元素
            resList.add(root.val);
            // 判断当前节点有无右子树
            root = root.right;
            // 如果右子树不为空,就将右子树的左边部分节点全部入栈
            while (root != null) {
                stack.push(root);
                root = root.left;
            }
        }
        return resList;
    }

    // 3.利用栈来实现后序遍历
    public static List<Integer> postOrder(TreeNode root) {
        if (root == null) {
            return new ArrayList<>();
        }
        List<Integer> resList = new ArrayList<>();
        // 准备两个栈,一个入栈,一个出栈 一个用于处理,一个用于收集
        Stack<TreeNode> inStack = new Stack<>();
        Stack<TreeNode> outStack = new Stack<>();
        inStack.push(root);
        TreeNode curNode;
        while (!inStack.isEmpty()) {
            curNode = inStack.pop();
            outStack.push(curNode);
            // 为什么这里是先左再右,原因是当前需要进入处理栈中,随后处理栈中的各个元素都要进入收集栈中
            // 先左再右进入处理栈,先右再左进入收集栈,最后使用集合记录元素时是先左再右后头的记录,刚好对应后序遍历
            if (curNode.left != null) {
                inStack.push(curNode.left);
            }
            if (curNode.right != null) {
                inStack.push(curNode.right);
            }
        }
        // 将收集栈中的各个元素添加到集合中
        while (!outStack.isEmpty()) {
            resList.add(outStack.pop().val);
        }
        // 返回集合即可
        return resList;
    }


    public static void main(String[] args) {
        TreeNode root = TreeNode.createTreeNode(new String[]{"1", "2", "3", "4", "5"});
        System.out.println(preOrder(root));
        System.out.println(inOrder(root));
        System.out.println(postOrder(root));
    }

}