二叉树前中后序遍历的递归及非递归实现(附代码)

完整代码见git仓库:https://github.com/wangshen2016/Algorithm
树结构如下:

static class Node{
        public int value;
        public Node lchild = null;
        public Node rchild = null;

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

        public Node(int value, Node lchild, Node rchild) {
            this.value = value;
            this.lchild = lchild;
            this.rchild = rchild;
        }
    }

1. 先序遍历

出栈顺序:头左右

  1. 准备一个栈
  2. 先压头节点
  3. 弹栈打印
  4. 如果有右孩子,压入右孩子
  5. 如果有左孩子,压入左孩子

递归

public static void pre(Node head) {
        if (head == null) {
            return;
        }
        System.out.print(head.value + " ");
        pre(head.lchild);
        pre(head.rchild);
    }

非递归

public static void pre2(Node head) {
        if (head == null) {
            return;
        }
        Deque<Node> stack = new ArrayDeque<>();
        stack.push(head);
        while (!stack.isEmpty()) {
            Node pop = stack.pop();
            System.out.print(pop.value + " ");
            if (pop.rchild != null) {
                stack.push(pop.rchild);
            }
            if (pop.lchild != null) {
                stack.push(pop.lchild);
            }
        }
    }

2. 后序遍历

方案一:使用两个栈

出栈顺序:头右左,然后倒过来就是后序遍历

  1. 准备一个栈
  2. 先压头节点
  3. 弹栈并压入另一个栈
  4. 如果有左孩子,压入左孩子
  5. 如果有右孩子,压入右孩子
  6. 最后依次弹出第二个栈并打印
方案二:使用一个栈

使用两个指针h,c。h记录上一次打印的节点,c记录栈顶元素

  1. 头节点入栈
  2. c记录栈顶元素
  3. if:如果c有左孩子且上一次打印的节点不是c的左右孩子,那么c的左孩子入栈,继续2;
    else if:如果c有右孩子,且上一次打印的不是c的右孩子,那么c的右孩子入栈,继续2;
    else:弹出栈顶元素并打印,h记录打印的元素

递归

public static void post(Node head) {
        if (head == null) {
            return;
        }
        post(head.lchild);
        post(head.rchild);
        System.out.print(head.value + " ");
    }

非递归方案一

public static void post2(Node head) {
        if (head == null) {
            return;
        }
        Deque<Node> stack = new ArrayDeque<>();
        Deque<Node> stack2 = new ArrayDeque<>();
        stack.push(head);
        while (!stack.isEmpty()) {
            Node pop = stack.pop();
            stack2.push(pop);
            if (pop.lchild != null) {
                stack.push(pop.lchild);
            }
            if (pop.rchild != null) {
                stack.push(pop.rchild);
            }
        }
        while (!stack2.isEmpty()) {
            System.out.print(stack2.pop().value + " ");
        }
    }

非递归方案2

public static void post3(Node h) {
        if (h == null) {
            return;
        }
        Deque<Node> stack = new ArrayDeque<>();
        Node c = null;
        stack.push(h);
        while (!stack.isEmpty()) {
            c = stack.peek();
            if (c.lchild != null && h != c.lchild && h != c.rchild) {
                stack.push(c.lchild);
            } else if (c.rchild != null && h != c.rchild) {
                stack.push(c.rchild);
            } else {
                Node pop = stack.pop();
                System.out.print(pop.value + " ");
                h = pop;
            }
        }
    }

3. 中序遍历

  1. 准备一个栈
  2. 将整条左子树依次入栈
  3. 如果左孩子为空,弹栈打印,并将当前节点指向其右孩子,继续到第2步执行

递归

public static void in(Node head) {
        if (head == null) {
            return;
        }
        in(head.lchild);
        System.out.print(head.value + " ");
        in(head.rchild);
    }

非递归

public static void in2(Node head) {
        if (head != null) {
            Deque<Node> stack = new ArrayDeque<>();
            while (!stack.isEmpty() || head != null) {
                if (head != null) {
                    stack.push(head);
                    head = head.lchild;
                } else {
                    head = stack.pop();
                    System.out.print(head.value + " ");
                    head = head.rchild;
                }
            }
        }
    }

4. 测试代码

public static void main(String[] args) {
        Node n1 = new Node(8);
        Node n2 = new Node(5);
        Node n3 = new Node(4);
        Node n4 = new Node(2);
        Node n5 = new Node(3);
        Node n6 = new Node(1);
        Node n7 = new Node(6);
        Node n8 = new Node(9);
        Node n9 = new Node(7);
        Node n10 = new Node(0);
        n1.lchild = n2;
        n1.rchild = n3;
        n2.lchild = n4;
        n2.rchild = n5;
        n3.rchild = n7;
        n5.lchild = n6;
        n7.lchild = n8;
        n8.lchild = n9;
        n8.rchild = n10;

        pre(n1);
        System.out.println();
        pre2(n1);
        System.out.println();
        in(n1);
        System.out.println();
        in2(n1);
        System.out.println();
        post(n1);
        System.out.println();
        post2(n1);
        System.out.println();
        post3(n1);
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值