递归和迭代实现二叉树先序、中序、后序和层序遍历

这篇具有很好参考价值的文章主要介绍了递归和迭代实现二叉树先序、中序、后序和层序遍历。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、递归方法

递归比较简单,直接上代码:

### 1.1 先序遍历

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    List<Integer> res = new ArrayList<Integer>();
    public List<Integer> preorderTraversal(TreeNode root) { 
        if(root == null){
            return res;
        }
        //将树节点的值保存在 List 中 便于后续输出
        res.add(root.val);
        preorderTraversal(root.left);
        preorderTraversal(root.right);
        return res;
    }
}

1.2 中序遍历

class Solution {
    List<Integer> res = new ArrayList<Integer>();
    public List<Integer> inorderTraversal(TreeNode root) { 
        if(root == null){
            return res;
        }
        inorderTraversal(root.left);
        res.add(root.val);
        inorderTraversal(root.right);
        return res;
}

1.3 后序遍历

class Solution {
    List<Integer> res = new ArrayList<Integer>();
    public List<Integer> postorderTraversal(TreeNode root) { 
        if(root == null){
            return res;
        }
        postorderTraversal(root.left);
        postorderTraversal(root.right);
        res.add(root.val);
        return res;
}    

二、迭代方法

能够用递归方法解决的问题基本都能用非递归方法实现。因为递归方法无非是利用函数栈来保存信息,可以寻找相应的数据结构替代函数栈,同样可以实现相同的功能。下面用栈,类比递归方法来统一实现三种遍历方式:

2.1 先序遍历

class Solution {
    public List<Integer> preorderTraversal(TreeNode root) {
        List<Integer> res = new ArrayList<Integer>();
    	Stack<TreeNode> nodeStack = new Stack<TreeNode>();
    	TreeNode node = root;
        while(node != null || !nodeStack.isEmpty()) { //当指针节点为空,遍历完所有节点时跳出循环
            if(node != null) { //依此遍历当前树最左边的节点。根据递归方法,挨个加入输出 list 中
               res.add(node.val);
               nodeStack.push(node);
               node = node.left;
            }else { //遍历完再看右子树
               node = nodeStack.pop();
               node = node.right;
            }
        }
        return res;
    }
}

2.2 中序遍历

class Solution {
    public List<Integer> inorderTraversal(TreeNode root) {
        List<Integer> res = new ArrayList<Integer>();
    	Stack<TreeNode> nodeStack = new Stack<TreeNode>();
    	TreeNode node = root;
        while(node != null || !nodeStack.isEmpty()) { //当指针节点为空,遍历完所有节点时跳出循环
            if(node != null) { //依此遍历当前树最左边的节点
               nodeStack.push(node);
               node = node.left;
            }else { //遍历完左子树最左节点后,根据递归方法,挨个加入进输出 list 中再看右子树
               node = nodeStack.pop();
               res.add(node.val);
               node = node.right;
            }
        }
        return res;
    }
}

2.3 后序遍历

其实后序遍历,可以利用前序遍历中先遍历右子树,形成 根->右子树->左子树 和后序完全相反的顺序,然后再将该顺序逆序,最后得到后序遍历的顺序。

class Solution {
    public List<Integer> postorderTraversal(TreeNode root) {
        List<Integer> res = new ArrayList<Integer>();
        Stack<TreeNode> nodeStack = new Stack<TreeNode>();
        Stack<TreeNode> rStack = new Stack<TreeNode>(); //用一个栈来进行最后 List 反转
        TreeNode node = root;
        while(node != null || !nodeStack.isEmpty()) { //当指针节点为空,遍历完所有节点时跳出循环
            if(node != null) { //依此遍历当前树最右边的节点
               rStack.push(node);
               nodeStack.push(node);
               node = node.right;
            }else { //遍历完右子树最右节点
               node = nodeStack.pop();
               node = node.left;
            }
        }
        while(!rStack.isEmpty()){
            res.add(rStack.pop().val);
        }
        return res;
    }
}

2.4 层序遍历

利用队列来实现层序遍历

基本思想是:

  • 入队就出队,并判断是否有子节点,使用当前队列中的元素作为限制条件
    • 有则入队,没有下一步
  • 当所有子节点为空,且全部节点出队后循环结束,输出队列
class Solution {
    public List<List<Integer>> levelOrder(TreeNode root) {
        //设置返回数组和队列
        List<List<Integer>> res = new ArrayList<List<Integer>>();
        Queue<TreeNode> Q = new LinkedList<TreeNode>();
        if(root == null) {
            return res;
        }
        Q.offer(root);
        //判断条件
        while(!Q.isEmpty()) {
            int size = Q.size();
            List<Integer> list = new ArrayList<Integer>();
            for(int i = 1; i <= size; i++) {
                TreeNode pnode = Q.poll();
                list.add(pnode.val);
                if(pnode.left != null) {
                    Q.offer(pnode.left);
                }
                if(pnode.right != null){
                    Q.offer(pnode.right);
                }
            }
            res.add(list);
        }
        return res;
    }
}

三、Morris 方法

最后无论是递归还是迭代方法,最后程序跑完结果需要的内存开销还是很大。这是由二叉树的结构所决定的,每个节点都有指向孩子节点的指针,但是没有指向父节点的指针,所以需要利用栈来实现子节点回到父节点的效果。

Morris 遍历的实质就是避免利用栈结构,让下层节点拥有指向上层的指针,具体是通过让底层节点指向 null 的空闲指针指向上层的某个节点,到达子节点指向父节点的效果。

详情可参考该博客, morris 方法日后有时间再研究。

Morris 算法进行二叉树遍历文章来源地址https://www.toymoban.com/news/detail-807667.html

到了这里,关于递归和迭代实现二叉树先序、中序、后序和层序遍历的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • C语言完整代码实现:二叉树的先序遍历、中序遍历、后序遍历

    一、先序遍历原理        先序遍历就是: 根、左、右 ,也就是先遍历根结点再遍历左结点最后再遍历右结点,注意:如果遍历到的结点不是叶子结点的话需要对该结点进行拆分,比如这棵二叉树: 先遍历 A ,然后是 B ,然后再是 C ,但是由于B并不是叶子结点,他本身又是

    2024年02月07日
    浏览(35)
  • 二叉树的先序、中序、后序遍历C++

    二叉树的节点结构如下所示 如下所示是一个二叉树,其中的每一个节点都是由上述TreeNode节点的一个具体对象。                                 图1 先遍历根(父)节点 、再遍历左节点、最后遍历右节点。 注意:这里说的遍历并不是行走。毕竟我们能够先取到的指针只

    2024年02月15日
    浏览(24)
  • 根据二叉树的先序、中序、后序遍历构建二叉树-图文详解

    引言:根据一颗二叉树,可以得出他的先序、中序、后序三种遍历方式,那么如果我们知道了他的前序、中序、后序遍历,如何绘制出这颗二叉树呢? 特性A,对于前序遍历,第⼀个肯定是根节点; 特性B,对于后序遍历,最后⼀个肯定是根节点; 特性C,利⽤前序或后序遍历

    2024年02月06日
    浏览(31)
  • 【数据结构】二叉树的创建和遍历(先序、中序、后序)

    最近一段时间学习了数据结构中二叉树的基本操作,包括二叉树的结构、二叉树的创建、递归先序中序后序遍历、非递归遍历等,想着把二叉树的相关知识和自己的见解放到网上来让网友看看是否正确,想和网友一起共同交流。 先了解一下二叉树的三个基本性质: 性质1:在

    2024年02月04日
    浏览(35)
  • 【树】建立二叉链表存储的二叉树+遍历二叉树(先序、中序、后序、层序)

    二叉树的构建利用了递归的原理,在按先序序列构建二叉树时,为了能让电脑知道每个结点是否有左右孩子,我们要对原二叉树进行 扩展 ,明确表示每个结点的左右孩子,若当前结点没有左右孩子,我们用’#\\\'表示。 由普通二叉树----扩展二叉树,如下图: 此时当我们按先序

    2024年02月07日
    浏览(27)
  • 【LeetCode】105. 从前序与中序遍历序列构造二叉树,106. 从中序与后序遍历序列构造二叉树,144. 二叉树的前序遍历非递归实现,94. 二叉树的中序遍历非递归实现,145. 二叉树的后序

    给定两个整数数组 preorder 和 inorder ,其中 preorder 是二叉树的 先序遍历 , inorder 是同一棵树的 中序遍历 ,请构造二叉树并返回其根节点。 示例 输入: preorder = [3,9,20,15,7], inorder = [9,3,15,20,7] 输出: [3,9,20,null,null,15,7] 给定两个整数数组 inorder 和 postorder ,其中 inorder 是二叉树的

    2024年02月04日
    浏览(28)
  • 十三、数据结构——二叉树的遍历(先序、中序和后序)详细思路和代码

    在数据结构中,二叉树是一种常用且重要的数据结构。二叉树的遍历是指按照一定顺序访问二叉树的所有节点,常见的遍历方式有前序遍历、中序遍历和后序遍历。本文将详细介绍这三种遍历算法,并介绍最优二叉树。 首先,我们先来了解一下二叉树的基本定义。二叉树是每

    2024年02月15日
    浏览(30)
  • 【数据结构】16 二叉树的定义,性质,存储结构(以及先序、后序、中序遍历)

    一个二叉树是一个有穷的结点集合。 它是由根节点和称为其左子树和右子树的两个不相交的二叉树组成的。 二叉树可具有以下5种形态。 一个二叉树第i层的最大结点数为 2 i − 1 2^{i-1} 2 i − 1 , i ≥ 1 i geq 1 i ≥ 1 每层最大结点可以对应完美二叉树(满二叉树),其所有分支结

    2024年02月20日
    浏览(33)
  • C语言实现非递归先序、中序、后序遍历

    闲来无事,回顾一下以前的学过的数据结构知识,面试也可以用到!!!    1、创建一颗二叉树 2、栈 3、非递归中序遍历 第一种 : 非递归中序遍历算法  第二种:非递归中序遍历算法 伪代码和算法详解: 4.非递归中序遍历完整代码 演示效果:    5.非递归先序遍历 第一种

    2024年02月07日
    浏览(22)
  • 【数据结构|二叉树遍历】递归与非递归实现前序遍历、中序遍历、后序遍历

    递归与非递归实现二叉树的前序遍历、中序遍历、后序遍历。 二叉树图 定义 前序遍历(Preorder Traversal): 前序遍历的顺序是先访问根节点,然后按照先左后右的顺序访问子节点。对于上面的二叉树,前序遍历的结果是:4 - 2 - 1 - 3 - 6 - 5 - 7。 中序遍历(Inorder Traversal): 中

    2024年02月14日
    浏览(34)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包