三行代码递归实现二叉树层序遍历

三行代码递归实现二叉树层序遍历简述二叉树的层序遍历网上大部分都是使用队列的出队和入队来实现的,这次我用三行代码递归实现二叉树的层序遍历.层序下图是一个简单的二叉树,层序就是一行一行的往下读取,这个二叉树的层序结果便是:1234567(图画的比较丑,强迫症看着难受,看官忍一下)递归分析要想使用递归,必须有两个条件:函数参数类型相同递归必须有出口在二叉树中找到上面的两个条件,与

大家好,又见面了,我是你们的朋友全栈君。

简述

二叉树的层序遍历网上大部分都是使用队列的出队和入队来实现的,这次我用三行代码递归实现二叉树的层序遍历.

层序

下图是一个简单的二叉树,层序就是一行一行的往下读取,这个二叉树的层序结果便是:
1234567

这里写图片描述
(图画的比较丑,强迫症看着难受,看官忍一下)

递归分析

要想使用递归,必须有两个条件:

  1. 函数参数类型相同
  2. 递归必须有出口

在二叉树中找到上面的两个条件,与前中后三种遍历一样,函数参数为节点的,递归出口是当左右孩子为空的时候.传入根节点,然后依次递归访问左右孩子,直至为空.

重点

那么问题来了,递归遍历的数据保存到那?如何做到保存后是层序的顺序?

继续观察这张图
这里写图片描述

第一层
根节点标记为1元素是层序输出的第一个值
第二层
标记为2的元素是层序输出的第二个值,同时他是标记为1节点的左孩子
标记为3的元素是层序输出的第三个元素,同时他是标记为1的节点的右孩子.
第三层
标记为4的元素是输出的第四个元素,他是标记为2节点的左孩子
标记为5的元素是输出的第五个元素,他是标记为2节点的右孩子

很容易找到一个规律:

  • 每一个节点左孩子在层序中输出的位置是该节点在层序输出位置的二倍
  • 每一个节点右孩子在层序中输出的位置是该节点在层序输出位置的二倍加一
  • 根节点在层序输出的位置为1

    也就是:
    假设当前节点输出的位置是i,那么他的左孩子层序输出的位置是2*i,他的右孩子在层序输出的位置为2*i+1

代码实现

根据上面得出的结论,就可以写出层序遍历的递归代码了,知道了节点层序输出的位置,那么遍历时候直接保存到指定位置,等所有节点遍历结束后再统一输出,这个与前中后遍历是不一样的.
既然是根据位置去保存,那么当然是使用数组了,位置就是数组的下标,根据下标进行存放,操作非常方便.

这一段代码,是把字符二叉树层序遍历

int tree2str(bitree *b,char *a,int i)
{
    if(b->left!=NULL)
    {
        tree2str(b->left,a,2*i);
    }
    if(b->right!=NULL)
    {
        tree2str(b->right,a,2*i+1);
    }
    *(a+i)=b->data;
}

注意
参数a为数组的首地址,调用时候传递参数i初始值为1,代表第一层,既就是根界点,当递归函数执行完毕时候,所有的元素都在对应的位置,a[0]元素始终为空,因为是从1开始存放的,所以调用之后输出的时候应该从a+1的位置开始,字符串结束应该是’\0’,输出前补上防错.
这里写图片描述
(本人测试环境:系统Ubuntu16.04LTS 编译器GCC5.4,字符串末尾没有添加’\0’未出错,在vc6.0会出现烫烫烫烫烫烫烫烫烫……)

结束

回到最初,标题说是三行代码,实际上为了看的方便在if函数后面加了花括号,我觉得一行代码的标志应该是一个分号,既一个语句;所以上面的也算是三行代码了.

如果上面的不算三行代码,那就看下面

int tree2str(bitree *b,char *a,int i)
{
    if(b->left!=NULL)       tree2str(b->left,a,2*i);
    if(b->right!=NULL)      tree2str(b->right,a,2*i+1);
    *(a+i)=b->data;
}

好了现在很直观的三行了[完].

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/143300.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • C++中构造函数的作用「建议收藏」

    C++中构造函数的作用「建议收藏」构造函数用于解决类中的对象初始化的问题构造函数是一类特殊的函数,与其他的成员函数不同的是构造函数构造函数不需要用户来调用它,而是建立对象的时候自动的执行#include//#include”student.h”//#include//#includeusingnamespacestd;classTime{publi

    2022年9月3日
    2
  • winscp登录主机拒绝_winscp连接被拒绝,winscp连接被拒绝的原因和解决办法详情

    winscp登录主机拒绝_winscp连接被拒绝,winscp连接被拒绝的原因和解决办法详情iis7服务器管理工具(曾用名:IIS7远程桌面):适用群体为:机房管理、站长、运维工作、程序员,等需要大量服务器或者电脑的用户朋友。IIS7服务器管理工具可以批量管理、定时上传下载、同步操作、数据备份、到期提醒、自动更新。IIS7服务器管理工具适用于Windows操作系统和liunx操作系统;支持Ftp客户端批量操作。问题解决方法尝试以下方法:1)开启|关闭防火墙(这里需要关闭)sudouf…

    2022年9月17日
    0
  • Django(55)GenericAPIView源码分析

    Django(55)GenericAPIView源码分析源码分析GenericAPIView继承自APIView,也就是在APIView基础上再做了一层封装,源码如下:classGenericAPIView(views.APIView):query

    2022年7月31日
    4
  • 推荐.Net、C# 逆向反编译四大工具利器(请勿用来非法行为)[通俗易懂]

    推荐.Net、C# 逆向反编译四大工具利器(请勿用来非法行为)[通俗易懂]在项目开发过程中,估计也有人和我遇到过同样的经历:运行环境出现了重大Bug亟需解决、或者由于电脑挂了、旧代码覆盖新代码,而在这种情况下,我们不能直接在当前的代码中修改这个Bug然后发布,这会导致更严重的问题,因为相当于版本回退了。还有电脑挂了代码整个都没有,这种情况下我们只能只能利用一些逆向的技巧和工具了来解析在服务器发布好的dll。那么你只是单纯的修改一个.Net程序集中的某个方法或功能,而

    2022年6月22日
    23
  • webpack css_webpack打包有哪些文件

    webpack css_webpack打包有哪些文件css文件处理-准备工作(以下项目配置都是基于上一篇webpack(4)的基础上)在项目开发中,我们必然需要添加很多的样式,而样式我们往往写到一个单独的文件中。这里我们就在src目录中创建一个n

    2022年7月30日
    2
  • MONTHS_BETWEEN函数「建议收藏」

    MONTHS_BETWEEN函数「建议收藏」 MONTHS_BETWEEN函数MONTHS_BETWEEN(x,y)用于计算x和y之间有几个月。如果x在日历中比y早,那么MONTHS_BETWEEN()就返回一个负数。注意:在调用MONTHS_BETWEEN函数时,日期的次序非常重要:如果想让结果为正数,稍晚的时间必须出现在前面。下面这个例子显示了2008年5月25日和2008年1月15日之间相差的月数。注意由于

    2022年7月12日
    23

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号