当前位置: 首页 > news >正文

DS链式二叉树的基本操作和OJ题(12)

文章目录

  • 前言
  • 一、二叉树节点个数
  • 二、二叉树叶子节点个数
  • 三、二叉树的高度
  • 四、二叉树第k层节点个数
  • 五、二叉树查找值为x的节点
  • 六、单值二叉树
  • 六、相同的二叉树
  • 七、二叉树的销毁
  • 八、翻转二叉树
  • 九、判断两棵树是否相同
  • 十、对称二叉树
  • 十一、平衡二叉树
  • 十二、二叉树的子树
  • 十三、二叉树的深度遍历
  • 十四、一道较难的综合题
  • 总结


前言

  承接上篇,正文开始!


一、二叉树节点个数

  我相信肯多人第一反应想到静态局部变量或者全局变量来解决这个问题

int TreeSize(TreeNode* root)
{static int size = 0;if (root == NULL){return 0;}++size;TreeSize(root->left);TreeSize(root->right);return size;
}int size = 0;
void TreeSize(TreeNode* root)
{if (root == NULL)return;++size;TreeSize(root->left);TreeSize(root->right);
}

  无论是使用静态还是全局变量,使得生命周期不会受到函数栈帧销毁的影响,可以解决求节点个数的问题,这倒是对的,可这size生命周期也太长了,静态还是全局变量只能被定义一次,这就意味着第一次计算出来的结果是正确的,那么第二次的结果会延用上一次变量存储的值,不会清空重新计数,第二次就错了

在这里插入图片描述

这里使用分治思想,可以将求整课树节点个数分为求左右子树节点个数加上根节点之和,不断划分

int BinaryTreeSize(TreeNode* root)
{if (root == NULL) return 0;return BinaryTreeSize(root->left) + BinaryTreeSize(root->right) + 1;
}

二、二叉树叶子节点个数

在这里插入图片描述
  我们也可以看出,这里也是使用了分治的思想,求整棵树叶子节点个数之和分为求左右子树叶子节点个数

  三种情况:空节点返回0,不是空节点,属于叶子节点返回1,不是空节点也不是叶子节点,使用分治等于左右子树叶子之和

int BinaryTreeLeafSize(TreeNode* root)
{if (root == NULL) return 0;if (root->left == NULL && root->right == NULL) return 1;return BinaryTreeLeafSize(root->left) + BinaryTreeLeafSize(root->right);
}

三、二叉树的高度

在这里插入图片描述
这里也是使用了分治的思想,求整棵树高度分为求左右子树高度之间最大的高度再+1

瑕疵版本:

//由于TreeHeight(root->left) > TreeHeight(root->right) 的比较是不会记录结果
//需要高的那一份再次递归调用
//因此多次递归调用 TreeHeight(root->left) 和 TreeHeight(root->right),造成重复计算
int TreeHeight(TreeNode* root)
{if (root == NULL) return 0;return TreeHeight(root->left) > TreeHeight(root->right) ?TreeHeight(root->left) + 1 : TreeHeight(root->right) + 1;
}

修正版本:

int TreeHeight(TreeNode* root) 
{if (root == NULL) return 0;int leftHeight = TreeHeight(root->left);int rightHeight = TreeHeight(root->right);return max(leftHeight, rightHeight) + 1;
}

四、二叉树第k层节点个数

在这里插入图片描述
第k层节点,就相当于是左右子树的 k - 1 层节点

int TreeLevelK(TreeNode* root, int k)
{assert(k > 0);if (root == NULL)return 0;if (k == 1)return 1;return TreeLevelK(root->left, k-1) + TreeLevelK(root->right, k-1);
}

五、二叉树查找值为x的节点

瑕疵版本:

TreeNode* TreeFind(TreeNode* root, BTDataType x)
{if (root == NULL) return NULL;if (root->data == x) return root;TreeFind(root->left, x);TreeFind(root->right, x);return NULL;
}

在这里插入图片描述
return 是return 上一层的,不是直接到最外层的

修正版本:

TreeNode* TreeFind(TreeNode* root, BTDataType x)
{if (root == NULL) return NULL;if (root->data == x) return root;TreeNode* ret1 = TreeFind(root->left, x);if (ret1) return ret1;TreeNode* ret2 =  TreeFind(root->right, x);if (ret2) return ret2;return NULL;
}

六、单值二叉树

力扣965.单值二叉树
在这里插入图片描述

bool isUnivalTree(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);
}

六、相同的二叉树

力扣100.相同的树
在这里插入图片描述

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);
}

七、二叉树的销毁

  后序遍历,因为肯定是要从后往前销毁的

void DestroyTree(TreeNode* root)
{if (!root) return;DestroyTree(root->left);DestroyTree(root->right);free(root);root = NULL;
}

八、翻转二叉树

力扣226.翻转二叉树
在这里插入图片描述

void _invertTree(struct TreeNode* root){if(root){struct TreeNode* tmp = root->left;root->left = root->right;root->right = tmp;_invertTree(root->left);_invertTree(root->right);}
}struct TreeNode* invertTree(struct TreeNode* root){_invertTree(root);return root;
}

九、判断两棵树是否相同

力扣100.相同的树
在这里插入图片描述

bool isSameTree(struct TreeNode* p, struct TreeNode* q) 
{if (!q && !p) return true;  //当两个节点都为空时,必为真if (!q || !p) return false; //当只有一个节点为空时候,必为假if (p->val != q->val) return false; //当相同位置的值不同时候,必为假return isSameTree(p->left, q->left) && isSameTree(p->right, q->right);
}

十、对称二叉树

力扣101.对称二叉树
在这里插入图片描述

class Solution {
public:bool _isSymmetric(TreeNode* root1, TreeNode* root2){if (!root1 && !root2) return true;else if (!root1 || !root2) return false;if (root1->val != root2->val) return false;return _isSymmetric(root1->left, root2->right) && _isSymmetric(root1->right, root2->left);}bool isSymmetric(TreeNode* root){return _isSymmetric(root->left, root->right);}
};

调皮一下,用一下Cpp代码
本题你可以思考一下何为对称,为什么要单独额外设置一个函数传两个节点指针

十一、平衡二叉树

力扣110.平衡二叉树
在这里插入图片描述

int maxDepth(struct TreeNode* root) {if (root == NULL) {return 0;}int LeftDepth = maxDepth(root->left);int RightDepth = maxDepth(root->right);return LeftDepth > RightDepth ? LeftDepth + 1 : RightDepth + 1;
}bool isBalanced(struct TreeNode* root) {if (root == NULL) {return true;}int LeftDepth = maxDepth(root->left);int RightDepth = maxDepth(root->right);return abs(LeftDepth - RightDepth) < 2&& isBalanced(root->left)&& isBalanced(root->right);
}

方法是如果左右子树的高度差不超过1并且左右子树均为平衡二叉树则为平衡二叉树

十二、二叉树的子树

力扣572.另一棵树的子树
在这里插入图片描述

class Solution {
public:bool isSameTree(TreeNode* p, TreeNode* q) {if (!p && !q){return true;}    else if ((p && !q) || (!p && q)){return false;}if (p->val != q->val){return false;}bool left = isSameTree(p->left, q->left);bool right = isSameTree(p->right, q->right);return left && right;  }bool isSubtree(TreeNode* root, TreeNode* subRoot) {if (!root) return false;if (isSameTree(root, subRoot)) return true;bool isLeft = isSubtree(root->left, subRoot);bool isRight = isSubtree(root->right, subRoot);return isLeft || isRight;}
};

又用了Cpp代码,其实也很好理解,先看下右根节点引出的树是否与子树相同,若相同直接返回true;若不相同,则判断下左右子树是否相同,就这样一直递归下去

十三、二叉树的深度遍历

  将二叉树的数值通过遍历存储到一个新的数组中,与前文不同的是,我们不只是打印数值,而是存储,这就是深度遍历,大家可以自行尝试一下:
力扣144.二叉树的前序遍历
力扣94.二叉树的中序遍历
力扣145.二叉树的后序遍历

十四、一道较难的综合题

  你是否对二叉树有所掌握了呢?来试试这道题吧!
牛客网KY11.二叉树遍历
在这里插入图片描述


总结

  这篇写的好痛苦~给个赞吧!


http://www.mrgr.cn/news/53081.html

相关文章:

  • 深入探讨ASP.NET Core中间件及其请求处理管道特性
  • 高校企业数据可视化平台功能介绍/特色功能
  • ruoyi框架配置多数据源
  • RK平台 GPIO序号转换软件
  • 基于SpringBoot+Vue+uniapp微信小程序的宿舍报修系统的详细设计和实现
  • 【PCB】ADAS
  • 乐观锁和悲观锁详解
  • 华为HCIE-Security认证考试流程、考试内容
  • 解析带有MyBatis语法的SQL字符串,获取最终的可执行SQL
  • 如何看待阿里通义千问团队发布Qwen2.5 MATH,效果怎么样,这是中国的草莓吗?
  • 自动化工具
  • 【数据结构与算法】之链表详解
  • 绿幕虚拟直播五大“硬件环境”
  • C++从入门到起飞之——红黑树 全方位剖析!
  • C++11新特性(4)
  • C语言根据日期计算星期
  • Android12.0进入默认Launcher前黑屏的解决办法
  • salary、wage与pay有啥区别?柯桥学商务英语到泓畅学校
  • 网站防护,高可用,雷池配置同步教程
  • Datawhale组队学习|全球AI攻防挑战赛——赛道二:AI核身之金融场景凭证篡改检测