上一次讲了二叉树前中后序遍历,这次讲一下标题上面的内容
那么就先看一下构建二叉树
下面就拿一个例题来看一下
就这个题,他是先构建二叉树,其中他给了一个字符串,这个字符串里面的#代表空,然后还是前序遍历,所以先构建二叉树
下面在看一下如何构建
就上面的这个字符串来说
那么我们先自己构建一下,其中这个是前序遍历,所以先根 在左 后右,所以我们可以构建
所以构建好就是这个样子,那么我们如何用程序构建呢?
下面我们就来看一下
这里我们看到,这个函数就是构建二叉树的,我们先看一下他的思想,他的思想就是如果为空的话,就说明构建结束了,如果不为空的话,那么就让指向这个字符串里面的非空向后走一个,让他的返回值充当该节点的孩子,所以还是递归思想,直到字符串结束
那么现在在看一下这个函数里面的参数,其中第一个是字符串,第二个是这个字符串里面字符的个数,第三个就是一个记录指向字符的变量,由于这个函数需要递归,所以传值并不能改变自己,所以只能传地址
下面就看一下如何实现
首先我们先想一下这个递归的结束条件,首先放*pi > n那么说明这个字符串已经结束了,直接返回空就可以了,还有一个就是在字符串中遇到了#,#代表着空,说明该树的孩子节点为空了
所以我们就是当*pi大于n就返回NULL,还有就是当*pi指向的字符串的位置#,那么就是返回空,如果他既不为#同时也满足*pi小于n,就说明该树还有孩子节点,又由于他是前序遍历,所以这里直接创建一个节点,把这个值赋值给这个节点,然后又是他的左树,所以继续调用自己,然后让*pi++,让他指向字符串的下一个位置,然后等他的左树构建完毕后继续调用自己构建右树即可。
二叉树的构建就是这样,还是可以试着画一下递归展开图,这样会更容易理解
下面我们看一下二叉树节点的个数
我们假设以这棵树为例
如果我们要数节点的个数,那么我们可以数他的子树的节点个数,只要得知他的子树的节点个数那么在加上他自己,就是这棵树的节点个数
所以我们如果想知道1这棵树的节点个数,那么我们就要知道1这个节点的两个子树的节点个数,如果我们想要知道1的左子树2这棵树的节点个数,那么我们就要知道2的两个子树的节点个数想加,所以我们就可以这样
下面还是画一下递归展开图
不过这里只画了1这个节点的左子树,而右子树和左子树画发也是相同的,所以就什略了。这里的代码也并不难理解,大家可以自己画一下
下面在看一下叶子节点的个数,还是和上面是一样的
这里讲一下思路也是分治思想
首先我们要求一棵树的叶子节点的个数,那么我们就要求他左子树节点的个数,加上右子树节点的个数,所以还是递归
这里我们看一下代码
所以这里的结束条件就是该节点的左右孩子都为空,都为空就为叶子节点所以返回1,如果这个节点为空当然直接返回0,所以我们记录他的左子树和右子树的节点个数,然后再返回他的左右子树节点个数想加就可以了。
下面我们在看一下第k层节点个数,其实和求叶子节点个数几乎一模一样,只不过条件不是两个孩子为空了,条件就变成是第k本的节点才返回1
下面我们看一下
首先还是讲一下思想,同样是分治
就用这棵树来说,假如我们要求他的第3层的节点个数
那么 第三本节点就是这一层
那么如果我们想要求第三层节点的个数那是不是就求A树第3-1层的节点的节点个数,以此类推,那么直到k等于1时,说明到达第k层,所以返回他第k层的节点个数
这里直接看代码,如果要求第k本的节点个数,那么就是输他孩子节点的第k-1 层的孩子个数,如果当这个节点为空时,就返回0,说明没有这个节点,如果当k等于1时,就返回1。然后记录他的左右子树的第k-1层节点个数想加即可
下面在看一个查找节点
我们先想一下,怎么才能查找到这个节点?我们肯定会想到遍历这棵树,如果这棵树有一个节点和想要查找的节点相同,那么就直接返回,如果没有找到直接返回空就可以了
下面我们就看一下代码
如果为空,就返回空,然后然后就可以比较改节点是否与想要查找的节点的值是否相同,如果相同就返回,如果不同的话就查看他的左右子树里面的值是否相同,然后我们可以记录他左右子树返回的值,如果不为空的话就说明找到了,如果为空的话我们就不看他的左子树,继续去看他的右子树,如果右子树返回的不为空,也直接返回该节点,如果为空我们就返回空
我们最后看一下层序遍历,我们这里可以说一下思想,其中层序遍历不需要用递归,那么我们应该用什么呢?
我们如何可以做到一层一层走
我们还是以这棵树为例
这里直接说思想,如果我们想要一层一层走,那么我们就是先走1然后2 3 5 4就是这样,那么我们要怎么样才可以做到
这里我们可以用一个队列
我们前面当然得判断1这个节点为不为空,如果不为空直接Push进去,如果为空,由于他是第一个节点,那么直接返回就可以了 ,然后我们在看1的两个孩子为不为空,如果不为空就Push进去如果为空就不用Push,然后我们在把1打印一下,然后Pop掉,这时候我们在看队列为不为空,如果为空的话那么就说明这棵树已经遍历完了,如果不为空,那我们就继续刚才的操作
此时我们在看队列头的节点的孩子为不为空,不为空就Push进来然后再打印后Pop掉,和上面的操作一样
我们下面看图片就清楚l
这时候已经把2的孩子Push进来了,然后再看3这个节点,由于他的孩子为空,所以不用Push进来
然后我们就剩下两个元素了,此时我们在看5这个节点,他的孩子同样为空
4这个节点的孩子也是为空,不用Push进来,然后就Pop掉4这个节点
最后队列为空,所以层序遍历结束