前言
上篇博客小L已经讲述了二叉树的基本性质目前初阶数据结构最难的一集-树+二叉树_堆-CSDN博客,这期我将带领大家一起进行二叉树的具体实现,由于普通二叉树实在太复杂,于是我们这节要一步步从零开始,那么就让我们系好安全带,一起向二叉树前进吧!!!
二叉树的遍历
递归遍历法
这里我们假设左右子树为空的节点为N然后我们来进行打印操作
遍历规则:左子树遍历完遍历其根,然后遍历右子树
1.前序遍历
根 左节点 右节点
首先将根打印出来,然后左子树向下走,走到底后返回到上一个根 ,根再重新走右子树,走到底后返回根,然后这个根作为上个根的左子树返回到上一个根,以此类推,直到返回到第一个根,然后走第一个根的右子树,右子树走完后返回根,至此递归遍历完成
其遍历的结果即为1 2 3 N N N 4 5 N N 6 N
2.中序遍历
左节点 根 右节点
与上面前序遍历不同的是 ,先遍历完左子树,再打印对应的根节点,最后遍历这个根的右子树
其遍历的结果即为 N 3 N 2 N 1 N 5 N 4 N 6 N
3.后序遍历
左节点 右节点 根
左右遍历完才走根
其遍历的结果即为 N N 3 N 2 N N 5 N N 6 4 1
学完相关的递归遍历后,我们就可以进行相关的二叉树中进行需要递归的操作
1.二叉树中节点的个数
有的哥们可能会利用多传一个size变量,size会随着递归的进行,进行增加但是每次递归返回到上一个函数时就会将空间划给操作系统,size的变化也会重新归为初始值
2.二叉树中树的高度
通过递归找到左右子树的高度,然后大的一棵树就为其高度
注意:比较前最好将左右子树的高度事先存储下来,以此来减少递归的次数,(因为如果直接利用三目操作符比较的话,会产生很多次重复递归)
3.二叉树第K层的节点个数
计算第K层的节点个数只要计算第k-1层左子树和右子树的总数即可
4. 二叉树查找值为x的结点
5.二叉树相关基础oj题
1.单值二叉树
965. 单值二叉树 - 力扣(LeetCode)https://leetcode.cn/problems/univalued-binary-tree/description/
思路:先比较根节点 , 根节点相同 , 然后再比较它的左右子树,如果左 / 右 子树存在的话,比较其是否相等
bool isUnivalTree(struct TreeNode* root) {
if (root == NULL )
return true;
if (root->left && root->left->val != root->val)
//当左子树存在则和左子树比较,如果写等于还得考虑右子树,所以索性写不等于
return false;
if (root->right && root->right->val != root->val)
//当右子树存在则和右子树比较,如果写等于还得考虑左子树,所以索性写不等于
return false;
return isUnivalTree(root->left) && isUnivalTree(root->right);//左右子树都相等则返回true
}
100. 相同的树 - 力扣(LeetCode)https://leetcode.cn/problems/same-tree/description/
思路:先判断两者的根节点是否相等,再递归到左右子树比较,
bool isSameTree(struct TreeNode* p, struct TreeNode* q) {
if (p == NULL && q == NULL)//当两者都同时为零时必定相等
return true;
if (p == NULL || q == NULL)//当一个为零另一个不为零时必定不等,但是由于前面相等结果已经写了,所以这样写
return false;
//判断根是否相同
if (p->val != q->val)//判断不等那么剩下的就是相等的情况,更好判断
return false;
return isSameTree(p->left, q->left) && isSameTree(p->right , q->right);//前面都没返回说明根节点已经相等
//只需左右节点相等就完成了
}
写完相同的树,我们就可以利用它来写它的相识题
Treesize(struct TreeNode* root)
{
return root == NULL ? 0 : Treesize(root->left) + Treesize(root->right)+1;//不能忘记加1
}
void preorder(struct TreeNode* root,int* a,int*pi)
{
if (root == NULL)
return ;
a[(*pi)++] = root->val;
preorder(root->left,a,pi);
preorder(root->right,a,pi);//递归返回到上一个函数时 i 的值会返回给操作系统,所以要用指针保存
}
int* preorderTraversal(struct TreeNode* root, int* returnSize) {
*returnSize = Treesize(root);//计算出二叉树节点的个数方便以后进行扩容注意解引用
int *a = (int*)malloc(sizeof(int)*(*returnSize));//为数组开辟空间,将传过来二叉树的值传给数组a来打印
int i = 0;//用来遍历原二叉树,因为每次都要进递归所以要传指针
preorder(root,a,&i);
return a;
}
思路:前面铁铁们已经写了如何判断树相同,以此思路,我们也可以写这个题
bool isSubsame(struct TreeNode* root, struct TreeNode* subRoot)
{
if(root == NULL && subRoot == NULL)
return true;
if(root == NULL || subRoot == NULL)
return false;
if(root->val != subRoot->val)
return false;
return isSubsame(root->left,subRoot->left) && isSubsame(root->right,subRoot->right);//要和subroot的左右子树比较
}
bool isSubtree(struct TreeNode* root, struct TreeNode* subRoot){
if(root == NULL)
return false;
if (root->val == subRoot->val && isSubsame(root , subRoot))
{
return true;
}
return isSubtree(root->left,subRoot) || isSubtree(root->right,subRoot);//左右子树只要有一个相同即可
}
非递归法
层序遍历
按照层数来从高到低进行遍历,主要遍历方法:首先将根节点存到队列中,然后每次取出一个根节点,取出的同时将他的儿子取到队列里,重复,直到全部取出
1.首先我们得将之前写的队列代码传过来,首先在文件里找到队列的代码,然后将它复制 下来,粘贴到现有项中
2.将
相关题目:判断是不是完全二叉树
思路:由于完全二叉树的叶子节点必须从左往右连续,所以遍历必须为层序遍历,所以我们可以联想到判断NULL的后面是否存在数据,如果存在数据那么肯定不是
二叉树的销毁
因为要采取左子树删完删右子树最后删除根节点,所以采用后序遍历的方式来进行删除
其他非递归遍历方法放在C艹和大家一起学习,尽请期待!
本文先就此结束,感谢大家的捧场