二叉树只看这一篇就够了,前/中/后序遍历(递归与非递归)

二叉树递归,看这篇文章就足够了。

二叉树的遍历,分为前序遍历、中序遍历、后序遍历。
 其中 注意两点:
 1. 前序,中序,后序遍历,这个"序"指的就是根
 2. 左子树优先于右子树
 

拿前序遍历举例:
前序遍历,这个"序"指的就是根。首先根要先遍历出来,然后是左子树, 最后是右子树。左子树有自己的下级子树,所以也就按照根+左子树+右子树的套路来排列。右子树也是如此。

下面代码注释中,构造了一个简单的二叉树,首先 6 -> 左子树(3/4/5)-> 右子树(7/8/9) ,左子树(3/4/5)也是按照套路根+左+右来排列,即5 -> 4 -> 3,右子树(7/8/9)也是按照套路根+左+右来排列,即7 -> 8 -> 9,所以汇总起来,这棵树的前序遍历即为 6 -> 5 -> 4 -> 3 -> 7 -> 8 -> 9

代码如下:
 

/**
 * 二叉树的遍历,前序、中序、后序
 * 注意两点:
 * 1. 前序中序后序,这个"序"指的就是根
 * 2. 左子树优先于右子树
 *
 * 比如说,
 * 前序遍历,这个"序"指的就是根。
 * 首先根要先遍历出来,
 * 然后是左子树(内部有子树,也是按照根+左子树+右子树木的套路来遍历),
 * 最后是右子树(内部有子树,也是按照根+左子树+右子树木的套路来遍历)。
 *
 */
public class TestNode {

    public static void main(String[] args) {

        /**
         *               6
         *             /  \
         *            5    7
         *           / \  / \
         *          4  3 8  9
         */
        Node root = new Node();
        root.setValue(6);
        root.setLeft(new Node().setValue(5).setLeft(new Node().setValue(4)).setRight(new Node().setValue(3)));
        root.setRight(new Node().setValue(7).setLeft(new Node().setValue(8)).setRight(new Node().setValue(9)));

        //前序遍历,输出 6 5 4 3 7 8 9
        preOrderTraversal(root);
        System.out.println("--------");

        //前序遍历
        preOrderTraversal1(root);
        System.out.println("--------");

        //中序遍历,输出 4 5 3 6 8 7 9
        inOrderTraversal(root);
        System.out.println("--------");

        //中序遍历,非递归
        inOrderTraversal1(root);
        System.out.println("--------");

        //后序遍历,输出 4 3 5 8 9 7 6
        postOrderTraversal(root);
        System.out.println("--------");

        //后序遍历,输出 4 3 5 8 9 7 6
        postOrderTraversal1(root);
        System.out.println("--------");

    }


    /**
     * 前序遍历,递归方式
     * @param root
     */
    private static void preOrderTraversal(Node root) {

        if (root == null) return;
        System.out.println(root.getValue());
        preOrderTraversal(root.getLeft());
        preOrderTraversal(root.getRight());
    }

    /**
     * 中序遍历,递归方式
     * @param root
     */
    private static void inOrderTraversal(Node root) {
        if (root == null) return;
        inOrderTraversal(root.getLeft());
        System.out.println(root.getValue());
        inOrderTraversal(root.getRight());
    }

    /**
     * 后序遍历,递归方式
     * @param root
     */
    private static void postOrderTraversal(Node root) {
        if (root == null) return;
        postOrderTraversal(root.getLeft());
        postOrderTraversal(root.getRight());
        System.out.println(root.getValue());
    }

    /**
     * 前序遍历,非递归方式
     */
    private static void preOrderTraversal1(Node root) {
        if (root == null) return;
        Stack<Node> stack = new Stack<Node>();

        //放入根节点
        stack.push(root);

        while (!stack.empty()) {
            //取出根节点
            Node p = stack.pop();
            System.out.println(p.getValue());

            //放入右子树
            if (p.getRight() != null) {
                stack.push(p.getRight());
            }

            //放入左子树
            if (p.getLeft() != null) {
                stack.push(p.getLeft());
            }
        }
    }

    /**
     * 中序遍历,非递归方式
     * @param root
     */
    private static void inOrderTraversal1(Node root) {
        if (root == null) return;

        Stack<Node> stack = new Stack<>();
        Node temp = root;
        while (temp != null || !stack.isEmpty()) {

            while (temp != null) {
                //当前节点的所有左孩子入栈
                stack.push(temp);
                temp = temp.getLeft();
            }

            //取出栈顶元素,即当前最左侧的子节点
            temp = stack.pop();
            System.out.println(temp.getValue());

            //栈顶元素存在右节点,则需要继续处理右节点的左节点,即进入重复
            if (temp.getRight() != null) {
                temp = temp.getRight();
            } else {
                temp = null;
            }
        }
    }

    /**
     * 后序遍历,非递归方式
     * @param root
     */
    private static void postOrderTraversal1(Node root) {
        if (root == null) return;

        Stack<Node> stack = new Stack<>();
        Node temp = root;
        Node pre = null;

        while (temp != null || !stack.isEmpty()) {

            while (temp != null) {
                stack.push(temp);
                temp = temp.getLeft();
            }


            if (!stack.isEmpty()) {
                temp = stack.peek();

                if (temp.getRight() == null || temp.getRight() == pre) {
                    temp = stack.pop();
                    System.out.println(temp.getValue());
                    pre = temp;
                    temp = null;
                } else {
                    temp = temp.getRight();
                }
            }
        }
    }
}


class Node {

    private int value;
    private Node left;
    private Node right;

    public int getValue() {
        return value;
    }

    public Node setValue(int value) {
        this.value = value;
        return this;
    }

    public Node getLeft() {
        return left;
    }

    public Node setLeft(Node left) {
        this.left = left;
        return this;
    }

    public Node getRight() {
        return right;
    }

    public Node setRight(Node right) {
        this.right = right;
        return this;
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值