二叉树遍历(先序,中序,后序)

本文详细介绍了如何使用递归和栈两种方法实现二叉树的先序、中序和后序遍历。递归方式中,先序、中序和后序遍历分别对应节点的首次、第二次和第三次访问。而栈的方式,先序遍历通过先压入头节点,再处理左右子节点;后序遍历则需要额外的栈辅助,将遍历顺序调整为左右头;中序遍历则遵循左头右的规则进行节点处理。
摘要由CSDN通过智能技术生成

一.用递归的方式

在这里插入图片描述

可以看到用递归的方式只是System.out.print(node.val+" ")位置不同而已

/**
 * @description: 二叉树
 * @create: 2021-05-22 15:50
 **/
public class treeTest {


    public static void main(String[] args) {
        Node node1=new Node(1);
        Node node2=new Node(2);
        Node node3=new Node(3);
        Node node4=new Node(4);
        Node node5=new Node(5);
        Node node6=new Node(6);
        Node node7=new Node(7);

        node1.leftChild=node2;
        node1.rightChild=node3;
        node2.leftChild=node4;
        node2.rightChild=node5;
        node3.leftChild=node6;
        node3.rightChild=node7;
        System.out.println("先序:");
        first(node1);
        System.out.println();
        System.out.println("中序:");
        mid(node1);
        System.out.println();
        System.out.println("后序:");
        last(node1);
    }

    /**
     * @Description  先序遍历,头->左->右
     * @Date 16:06 2021/5/22
     * @Param [node]
     * @return void
     **/
    public static void first(Node node){
       if(node==null){
           return;
       }
        System.out.print(node.val+" ");
        first(node.leftChild);
        first(node.rightChild);
    }

    /**
     * @Description  中序遍历,左->头->右
     * @Date 16:06 2021/5/22
     * @Param [node]
     * @return void
     **/
    public static void mid(Node node){
        if(node==null){
            return;
        }

        mid(node.leftChild);
        System.out.print(node.val+" ");
        mid(node.rightChild);
    }

    /**
     * @Description  后序遍历,左->右->头
     * @Date 16:06 2021/5/22
     * @Param [node]
     * @return void
     **/
    public static void last(Node node){
        if(node==null){
            return;
        }

        last(node.leftChild);
        last(node.rightChild);
        System.out.print(node.val+" ");
    }


    static class Node{
        Node parent;
        Node leftChild;
        Node rightChild;
        int val;
        public Node(Node parent, Node leftChild, Node rightChild,int val) {
            super();
            this.parent = parent;
            this.leftChild = leftChild;
            this.rightChild = rightChild;
            this.val = val;
        }

        public Node(int val){
            this(null,null,null,val);
        }

        public Node(Node node,int val){
            this(node,null,null,val);
        }

    }

}
用递归的方法,每个节点都会执行3次,
先序:同一个节点第一次到达就打印
中序:同一个节点第二次到达就打印
后序:同一个节点第三次达到就打印

在这里插入图片描述

二.用栈的方式

1.先序:头左右

(1)把头结点先压入栈
(2)结点弹出就打印
(3)如有右结点,压入右
(3)如有左结点,压入左

例子:首先放入头结点1,弹出打印1,然后把右结点3放入,再放左结点2,弹出2并打印,然后放入右结点5,然后放入左结点4, 4和5都没有子结点,先弹4,在弹5,然后弹3,然后压入7,然后压入6,弹出6,和7,先序就完成了:1 2 4 5 3 6 7
在这里插入图片描述

  public static void firstStack(Node node) {
        //先加入头结点,然后弹出打印,有右入右,然后有左入左
        if (node != null) {
            Stack<Node> stack = new Stack<Node>();
            stack.push(node);

            while (!stack.empty()) {
                Node n = stack.pop();
                System.out.print(n.val + " ");
                if (n.rightChild != null) {
                    stack.push(n.rightChild);
                }
                if (n.leftChild != null) {
                    stack.push(n.leftChild);

                }
            }
        }
    }

2.后序:左右头

按照 先头,左,右的方法放入结点,弹出来的结点顺序是1,3,7,6,2,5,4,从右往左看刚好是后序的排列,所以把先弹出来的放入新的栈里

(1)把头结点先压入栈

(2) 结点弹出到另一个栈中

(3)如有左结点,压入左

(3)如有右结点,压入右

在这里插入图片描述

public static void lastStack(Node node) {

        if (node != null) {
            Stack<Node> stack = new Stack<Node>();
            Stack<Node> result = new Stack<Node>();
            stack.push(node);

            while (!stack.empty()) {
                Node n = stack.pop();
                result.push(n);
                if (n.leftChild != null) {
                    stack.push(n.leftChild);

                }
                if (n.rightChild != null) {
                    stack.push(n.rightChild);
                }
            }
            while(!result.empty()){
                System.out.print(result.pop().val+" ");
            }
        }
    }

后序的第二种方法,避免了创建另一个stack来完成排序。

  public static void lastStack2(Node node) {

        if (node != null) {
            Stack<Node> stack = new Stack<Node>();
            stack.push(node);
            Node c=null;
            while (!stack.empty()) {
                //获取栈顶的位置,但不弹出
                c = stack.peek();
                   //先把左结点全部进栈
                if (c.leftChild != null && node!=c.leftChild && node!=c.rightChild) {
                    stack.push(c.leftChild);
                    //处理当前栈顶右节点,如果有就入栈
                }else if(c.rightChild!=null && node!=c.rightChild){
                    stack.push(c.rightChild);
                }else{
                    //处理当前栈顶左右节点都处理完成,当前栈顶节点出栈,并且打印,node每次指向的是
                    //出栈的那个节点
                    System.out.print(stack.pop().val+" ");
                    node=c;
                }
            }

        }
    }

3.中序:左头右

规则一:整颗数左边界依次压入栈
规则二:当没有左节点时就弹出打印。找到该节点的右数执行规则一
例子:先压入1,2,4,然后弹出4并打印,4没有右数节点,就往回走,弹出2,然后找到2的右数5压栈,
5没有右节点弹出打印,然后弹出1打印,找到1的右节点3执行规则一,把3,6都压栈,6没有右节点,直接弹出打印,然后弹出3,找到3的右节点7,然后入栈,然后7没有节点直接弹出打印

在这里插入图片描述

public static void minStack(Node node) {

        if (node != null) {
            Stack<Node> stack = new Stack<Node>();

            while (!stack.empty() || node!=null) {
                //如果node为空,说明没有左结点,弹出打印当前结点
                if(node!=null){
                    stack.push(node);
                    node=node.leftChild;
                }else{
                    //循环加入node!=null,是在node.rightChild为空的情况下,
                    // 说明该节点左右节点都没有,往回走,出来上一个节点
                    node=stack.pop();
                    System.out.print(node.val+" ");
                    node=node.rightChild;
                }
            }
        }
    }
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值