二十三、二叉树的前、中、后序遍历(递归和非递归)

public class PreInPosTraversal {

    public static class Node {
        public int number;
        public String name;
        public Node left;
        public Node right;
        public Node(int number, String name) {
            this.number = number;
            this.name = name;
        }
        @Override
        public String toString() {
            return "Node{" +
                    "number=" + number +
                    ", name='" + name + '\'' +
                    '}';
        }
    }

    /**
     * 递归前序遍历
     * @param head
     */
    public static void preOrderRecur(Node head, List<String> res) {
        if (head == null) {
            return;
        }
        res.add(head.name);
        preOrderRecur(head.left, res);
        preOrderRecur(head.right, res);
    }

    /**
     * 递归中序遍历
     * @param head
     */
    public static void inOrderRecur(Node head, List<String> res) {
        if (head == null) {
            return;
        }
        inOrderRecur(head.left, res);
        res.add(head.name);
        inOrderRecur(head.right, res);
    }

    /**
     * 递归后续遍历
     * @param head
     */
    public static void posOrderRecur(Node head, List<String> res) {
        if (head == null) {
            return;
        }
        posOrderRecur(head.left, res);
        posOrderRecur(head.right, res);
        res.add(head.name);
    }

    /**
     * 非递归前序遍历:中 左 右
     * 压头节点,然后先压右再压左(没有就不压)
     * 因为每一次要弹出一个所以要先压右,再压左,左先出,右后出
     * @param head
     */
    public static List<String> preOrderUnRecur(Node head) {
        ArrayList<String> res = new ArrayList<>();
        if (head != null) {
            Stack<Node> stack = new Stack<>();
            //首先将父节点入栈
            stack.add(head);
            //当栈不为空的时候
            while (!stack.isEmpty()) {
                //最先弹出的是父节点
                Node curNode = stack.pop();
                res.add(curNode.name);
                //中序遍历,左在右的前面,右子节点先入栈
                if (curNode.right != null) {
                    stack.push(curNode.right);
                }
                //中序遍历,左在右的前面,左子节点后入栈
                if (curNode.left != null) {
                    stack.push(curNode.left);
                }
            }
        }
        return res;
    }

    /**
     * 非递归中序遍历:左 中 右
     * 如果当前节点为空,从栈中弹出一个打印,当前节点往右
     * 如果当前节点不为空,当前节点入栈,然后往左
     * @param head
     */
    public static List<String> inOrderUnRecur(Node head) {
        ArrayList<String> res = new ArrayList<>();
        if (head != null) {
            Node curNode = head;
            Stack<Node> stack = new Stack<>();
            while (!stack.isEmpty() || curNode != null) {
                //当前节点不为空,往左串
                if (curNode != null) {
                    stack.push(curNode);
                    curNode = curNode.left;
                } else {
                    //当前节点为空,从栈中拿出一个,打印,往右串
                    curNode = stack.pop();
                    res.add(curNode.name);
                    curNode = curNode.right;
                }
            }
        }
        return res;
    }

    /**
     * 前序是: 中 左 右 ——> 改为: 中 右 左 即先压左,再压右
     * 这时候上面的出栈顺序就是 中 右 左,出栈后再入另一个栈
     * 然后再出栈就是:左 右 中 的顺序,即后续
     * @param head
     */
    public static List<String> posOrderUnRecur1(Node head) {
        ArrayList<String> res = new ArrayList<>();
        if (head != null) {
            Stack<Node> s1 = new Stack<>();
            Stack<Node> s2 = new Stack<>();
            s1.push(head);
            while (!s1.isEmpty()) {
                // 出栈
                Node curNode = s1.pop();
                //这个时机就是前序遍历的打印,我们在这里放入栈中
                //System.out.print(curNode.name + " ");
                // 放入到另一个栈中
                s2.push(curNode);
                // 先向左再向右,出栈就是 中 右 左
                if (curNode.left != null) {
                    s1.push(curNode.left);
                }
                if (curNode.right != null) {
                    s1.push(curNode.right);
                }
            }
            while (!s2.isEmpty()) {
                // 此时从s2出栈就是 左 右 中
                res.add(s2.pop().name);
            }
        }
        return res;
    }

    //炫技
    public static List<String> posOrderUnRecur2(Node head) {
        ArrayList<String> res = new ArrayList<>();
        if (head != null) {
            Stack<Node> stack = new Stack<>();
            stack.push(head);
            Node curNode;
            while (!stack.isEmpty()) {
                curNode = stack.peek();
                if (curNode.left != null && head != curNode.left && head != curNode.right) {
                    stack.push(curNode.left);
                } else if (curNode.right != null && head != curNode.right) {
                    stack.push(curNode.right);
                } else {
                    res.add(stack.pop().name);
                    head = curNode;
                }
            }
        }
        return res;
    }

    public static void main(String[] args) {
        Node head = new Node(1, "中国");
        Node node1 = new Node(2, "广东");
        Node node2 = new Node(3, "四川");
        Node node3 = new Node(4, "广州");
        Node node4 = new Node(5, "佛山");
        Node node5 = new Node(6, "成都");
        Node node6 = new Node(7, "绵阳");
        ArrayList<String> res1 = new ArrayList<>();
        ArrayList<String> res2 = new ArrayList<>();
        ArrayList<String> res3 = new ArrayList<>();
        head.left = node1;
        head.right = node2;
        node1.left = node3;
        node1.right = node4;
        node2.left = node5;
        node2.right = node6;

        // 递归
        System.out.print("递归前序遍历:");
        preOrderRecur(head, res1);
        System.out.println(res1);
        System.out.print("递归中序遍历:");
        inOrderRecur(head,res2);
        System.out.println(res2);
        System.out.print("递归后序遍历:");
        posOrderRecur(head,res3);
        System.out.println(res3);
//      递归前序遍历:[中国, 广东, 广州, 佛山, 四川, 成都, 绵阳]
//      递归中序遍历:[广州, 广东, 佛山, 中国, 成都, 四川, 绵阳]
//      递归后序遍历:[广州, 佛山, 广东, 成都, 绵阳, 四川, 中国]

        // 非递归
        List<String> res4 = preOrderUnRecur(head);
        System.out.println("非递归前序遍历:"+res4);
        List<String> res5 = inOrderUnRecur(head);
        System.out.println("非递归中序遍历:"+res5);
        List<String> res6 = posOrderUnRecur1(head);
        System.out.println("非递归后序遍历:"+res6);
        List<String> res7 = posOrderUnRecur2(head);
        System.out.println("非递归后序遍历:"+res7);
    }

//    非递归前序遍历:[中国, 广东, 广州, 佛山, 四川, 成都, 绵阳]
//    非递归中序遍历:[广州, 广东, 佛山, 中国, 成都, 四川, 绵阳]
//    非递归后序遍历:[广州, 佛山, 广东, 成都, 绵阳, 四川, 中国]
//    非递归后序遍历:[广州, 佛山, 广东, 成都, 绵阳, 四川, 中国]

}

递归遍历:
在这里插入图片描述
非递归的中序遍历思路:
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值