二叉树的遍历

二叉树是数据结构中的基础知识,也是面试笔试中的重要考点,在实际开发中也会用的比较多。要想解决二叉树相关的问题,就必须深刻理解二叉树的三种遍历六种算法!
(后序遍历递归方法的执行过程)
在这里插入图片描述
在这里插入图片描述
1.前序遍历
跟节点—>左子树—>右子树
对所有子树进行这样的遍历操作就得到前序遍历序列:DBACFEG
I.递归形式:先给出代码:

    public void preorder_traversal_recursion(TreeNode root){
        if (root==null)return;
        System.out.print(root.val);
        preorder_traversal_recursion(root.left);
        preorder_traversal_recursion(root.right);
    }

递归具有很强的描述能力所以代码很简短,但其抽象性很高,不便于理解前序遍历的原理。这里给出解释:
递归调用是基于栈完成的,每次自己调用自己时都会将当前状态压入递归栈,转而执行新被调用的方法,再调用自己时再压入栈,直到遇到递归出口return,最下层的函数执行完毕出栈,接着执行上一层未执行完的函数。
过程如下:
①读取D,进栈
在这里插入图片描述
②读取B,进栈
在这里插入图片描述
③读取A,进栈
在这里插入图片描述
④满足返回条件,root=null,出栈到B,接着C进栈,读取C
在这里插入图片描述
⑤满足root==null返回,出栈到B,B中函数体执行完毕,返回出栈到D,接着F进栈,读取F。遍历右子树和左子树类似,不再赘述。

非递归形式(迭代):其实迭代原理和上面的一模一样,只不过换用栈来代替递归。
①根节点左子树非空,一直进栈到左子树为空。这时,可以读取DBA
在这里插入图片描述
②左子树为空,那就看看又子树,出栈到B,C进栈,读取C,得到DBAC.又发现左子树为空,这时C左右子树均为空,出栈到D,接着右子树进栈。
在这里插入图片描述

    public void preorder_traversal_iteration(TreeNode root){
        if (root==null)return;
        Stack<TreeNode> stack=new Stack<>();
        TreeNode curr=root;
        while (!stack.isEmpty()||curr!=null){
            if (curr!=null){//一直进栈左子树节点,直到为null
                System.out.print(curr.val);
                stack.push(curr);
                curr=curr.left;
            }else {//左节点为空,则出栈选择右节点
                curr=stack.pop().right;
            }
        }
    }

2.中序遍历
把根节点放在中间遍历
左子树—>根节点—>右节点
即ABCDEFG(中序遍历在平衡二叉树运用的比较多,平衡二叉树的中序遍历是有序的,另外根据中序遍历序列和前序遍历序列或者后序遍历序列组合可以确定一个二叉树)
递归形式:
同样先上代码:

    public void inorder_recursion(TreeNode root){
        if (root==null)return;
        inorder_recursion(root.left);
        System.out.print(root.val);
        inorder_recursion(root.right);
    }

过程如下:
I.一直进栈,一直到左子树的最左端,出栈读取A
在这里插入图片描述
II.出栈,读取B,进栈发现C左子树为null,出栈读取C,发现C的右子树为空
出栈到D
III.出栈读取D,D的右子树不为空,则进入D的右子树,一直进栈到F的最左端。出栈读取E,出栈读取F,出栈读取G

迭代形式:

    public void inorder_iteration(TreeNode root){
        if (root==null)return;
        Stack<TreeNode> stack=new Stack<>();
        TreeNode curr=root;
        while (!stack.isEmpty()||curr!=null){
            if (curr!=null){
                stack.push(curr);
                curr=curr.left;
            }else {
                TreeNode t=stack.pop();
                System.out.print(t.val);
                curr=t.right;
            }
        }
    }

I.前序遍历是在进栈的时候读取节点,中序遍历是在出栈的时候读取节点。
设置一个curr节点记录当前节点
从根节点开始,一直进栈到最左端,发现A的左子树为空,出栈,使curr=A.right,发现curr为空,出栈读取B,使curr=B.right。如此重复得到中序序列。
在这里插入图片描述
③后序遍历:
左子树—>右子树—>根节点
ACBEGFD
递归形式:

    public void subsequent_traversal(TreeNode root){
        if (root==null)return;
        subsequent_traversal(root.left);
        subsequent_traversal(root.right);
        System.out.print(root.val);
    }

后序遍历比前两种遍历稍微复杂一些
过程如下:递归方法的执行过程,顺着箭头方向
在这里插入图片描述
迭代形式:

    public void subsequent_traversal_iteration(TreeNode root) {
        if (root == null) return;
        Stack<TreeNode> stack = new Stack<>();
        TreeNode curr = root;
        TreeNode pre = null;
        while (!stack.isEmpty() || curr != null) {
            if (curr != null) {
                stack.push(curr);
                curr = curr.left;
            } else {
                System.out.print(stack.pop());
                curr = stack.peek().right;
            }
        }
    }

ps:为了加深对二叉树遍历的理解,我们给出两个问题:
在这里插入图片描述
在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值