二叉树层序遍历 构建二叉树 二叉树节点数 第k层节点数 查找

上一次讲了二叉树前中后序遍历,这次讲一下标题上面的内容

那么就先看一下构建二叉树

下面就拿一个例题来看一下

216b9d79d43c4924b3d3bd6065ef5a8a.png

就这个题,他是先构建二叉树,其中他给了一个字符串,这个字符串里面的#代表空,然后还是前序遍历,所以先构建二叉树

下面在看一下如何构建

 

就上面的这个字符串来说

9aa600726c2e4b7597d6a24202c66bbb.png 

那么我们先自己构建一下,其中这个是前序遍历,所以先根 在左 后右,所以我们可以构建

 74f82609468a477892c00346ded90bce.png

 所以构建好就是这个样子,那么我们如何用程序构建呢?

下面我们就来看一下

6174932ce7dd4bdd93e6b47d964d90d8.png

 这里我们看到,这个函数就是构建二叉树的,我们先看一下他的思想,他的思想就是如果为空的话,就说明构建结束了,如果不为空的话,那么就让指向这个字符串里面的非空向后走一个,让他的返回值充当该节点的孩子,所以还是递归思想,直到字符串结束

那么现在在看一下这个函数里面的参数,其中第一个是字符串,第二个是这个字符串里面字符的个数,第三个就是一个记录指向字符的变量,由于这个函数需要递归,所以传值并不能改变自己,所以只能传地址

下面就看一下如何实现

首先我们先想一下这个递归的结束条件,首先放*pi > n那么说明这个字符串已经结束了,直接返回空就可以了,还有一个就是在字符串中遇到了#,#代表着空,说明该树的孩子节点为空了

所以我们就是当*pi大于n就返回NULL,还有就是当*pi指向的字符串的位置#,那么就是返回空,如果他既不为#同时也满足*pi小于n,就说明该树还有孩子节点,又由于他是前序遍历,所以这里直接创建一个节点,把这个值赋值给这个节点,然后又是他的左树,所以继续调用自己,然后让*pi++,让他指向字符串的下一个位置,然后等他的左树构建完毕后继续调用自己构建右树即可。

二叉树的构建就是这样,还是可以试着画一下递归展开图,这样会更容易理解

下面我们看一下二叉树节点的个数

80b5d48e00e047089234e7d5b2c07f2b.png

我们假设以这棵树为例

如果我们要数节点的个数,那么我们可以数他的子树的节点个数,只要得知他的子树的节点个数那么在加上他自己,就是这棵树的节点个数

a190bdbdd42846c9b26b6f4f5075b968.png 

所以我们如果想知道1这棵树的节点个数,那么我们就要知道1这个节点的两个子树的节点个数,如果我们想要知道1的左子树2这棵树的节点个数,那么我们就要知道2的两个子树的节点个数想加,所以我们就可以这样

d110b86d372f42a5a2b198b239c40bb7.png 

 下面还是画一下递归展开图

67c0e951d3834f32a301b7fddeaff184.png

不过这里只画了1这个节点的左子树,而右子树和左子树画发也是相同的,所以就什略了。这里的代码也并不难理解,大家可以自己画一下

 下面在看一下叶子节点的个数,还是和上面是一样的

这里讲一下思路也是分治思想

首先我们要求一棵树的叶子节点的个数,那么我们就要求他左子树节点的个数,加上右子树节点的个数,所以还是递归

这里我们看一下代码

79d155afc2854639b79bf4c01a559c02.png

所以这里的结束条件就是该节点的左右孩子都为空,都为空就为叶子节点所以返回1,如果这个节点为空当然直接返回0,所以我们记录他的左子树和右子树的节点个数,然后再返回他的左右子树节点个数想加就可以了。

下面我们在看一下第k层节点个数,其实和求叶子节点个数几乎一模一样,只不过条件不是两个孩子为空了,条件就变成是第k本的节点才返回1

下面我们看一下

首先还是讲一下思想,同样是分治

 

 22fc271c26324ebead7668dd29acb143.png

就用这棵树来说,假如我们要求他的第3层的节点个数

那么 第三本节点就是这一层

1f2698b0f91d4cfd86cdd8d78173f1aa.png

那么如果我们想要求第三层节点的个数那是不是就求A树第3-1层的节点的节点个数,以此类推,那么直到k等于1时,说明到达第k层,所以返回他第k层的节点个数

0c9a2cc4ba534960a9675c11db577150.png

这里直接看代码,如果要求第k本的节点个数,那么就是输他孩子节点的第k-1 层的孩子个数,如果当这个节点为空时,就返回0,说明没有这个节点,如果当k等于1时,就返回1。然后记录他的左右子树的第k-1层节点个数想加即可

下面在看一个查找节点

我们先想一下,怎么才能查找到这个节点?我们肯定会想到遍历这棵树,如果这棵树有一个节点和想要查找的节点相同,那么就直接返回,如果没有找到直接返回空就可以了

下面我们就看一下代码 

e6ef2421dd8c4833b3e24f2b602dc28d.png

如果为空,就返回空,然后然后就可以比较改节点是否与想要查找的节点的值是否相同,如果相同就返回,如果不同的话就查看他的左右子树里面的值是否相同,然后我们可以记录他左右子树返回的值,如果不为空的话就说明找到了,如果为空的话我们就不看他的左子树,继续去看他的右子树,如果右子树返回的不为空,也直接返回该节点,如果为空我们就返回空

 

我们最后看一下层序遍历,我们这里可以说一下思想,其中层序遍历不需要用递归,那么我们应该用什么呢?

我们如何可以做到一层一层走

 12f0768ee9eb4bafbb6818610a058456.png

我们还是以这棵树为例

这里直接说思想,如果我们想要一层一层走,那么我们就是先走1然后2 3 5 4就是这样,那么我们要怎么样才可以做到

这里我们可以用一个队列

 8e4be4243a334214a0b9e5538809aea3.png

我们前面当然得判断1这个节点为不为空,如果不为空直接Push进去,如果为空,由于他是第一个节点,那么直接返回就可以了 ,然后我们在看1的两个孩子为不为空,如果不为空就Push进去如果为空就不用Push,然后我们在把1打印一下,然后Pop掉,这时候我们在看队列为不为空,如果为空的话那么就说明这棵树已经遍历完了,如果不为空,那我们就继续刚才的操作

f750a6b0cf244593943b801a88723158.png

此时我们在看队列头的节点的孩子为不为空,不为空就Push进来然后再打印后Pop掉,和上面的操作一样

我们下面看图片就清楚l

f7331047e6ad43889149e8a50b65d400.png

 这时候已经把2的孩子Push进来了,然后再看3这个节点,由于他的孩子为空,所以不用Push进来

34727ebf7d9c439987fe829752472d97.png

 然后我们就剩下两个元素了,此时我们在看5这个节点,他的孩子同样为空

7bd382ef7d3149c1bfc3893892e809e9.png

 4这个节点的孩子也是为空,不用Push进来,然后就Pop掉4这个节点

403f161330ec4f279a83f1a9e194025e.png

 最后队列为空,所以层序遍历结束

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Naxx Crazy

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值