由于二叉树是数据结构中偏难的一块,这里我们先熟悉二叉树的结构,再具体来实现一颗二叉树,采用手动构建二叉树的方式,帮助大家进一步理解
呈现的是一个树型结构
BTNode *BinaryTreeCreate(char ch)
{
BTNode *newNode = (BTNode *)malloc(sizeof(BTNode));
newNode->data = ch;
newNode->left = NULL;
newNode->right = NULL;
return newNode;
}
void func()
{
BTNode* A = BinaryTreeCreate('A');
BTNode* B = BinaryTreeCreate('B');
BTNode* C = BinaryTreeCreate('C');
BTNode* D = BinaryTreeCreate('D');
BTNode* E = BinaryTreeCreate('E');
BTNode* F = BinaryTreeCreate('F');
A->left = B;
A->right = C;
B->left = D;
C->left = E;
C->right = F;
}
构建了结点与结点之间的父子关系,从代码中可以看到A的左右子树是B和C,B的左子树是D,C的左右子树是E和F,剩余的默认给NULL值,在创建结点的时候就已经初始化好了,那如果想要呈现出遍历顺序呢。
#pragma once
#include<memory.h>
#include<stdbool.h>
#include<stdlib.h>
#include<stdio.h>
#include"Queue.h"
typedef char BTDataType;
typedef struct BTNode
{
struct BTNode *left;
struct BTNode *right;
BTDataType data;
}BTNode;
//创建结点
BTNode *BinaryTreeCreate(char ch);
//后序遍历
void PrevOrder(BTNode *root);
//中序遍历
void Inorder(BTNode *root);
//后序遍历
void Postorder(BTNode *root);
//树结点的个数
int BinaryTreeSize(BTNode *root);
//求叶子结点的个数
int BinaryleafSize(BTNode* root);
//求二叉树的第k层结点个数
int BinaryKSize(BTNode* root,int k);
//查找值为val的结点
BTNode* BinaryFind(BTNode* root,char ch);
//广度优先遍历二叉树
void TreeLevelorder(BTNode* root);
//二叉树的销毁
void BinaryTreeDestroy(BTNode* root);
//判断一颗树是不是完全二叉树
bool BinaryTreecomp(BTNode* root);
#include"BinaryTree.h"
BTNode *BinaryTreeCreate(char ch)
{
BTNode *newNode = (BTNode *)malloc(sizeof(BTNode));
assert(newNode);
newNode->data = ch;
newNode->left = NULL;
newNode->right = NULL;
return newNode;
}
//后序遍历
void PrevOrder(BTNode *root)
{
if (root == NULL)
{
printf("NULL ");
return;
}
else
{
PrevOrder(root->left);
PrevOrder(root->right);
printf("%c ",root->data);
}
}
//中序遍历
void Inorder(BTNode *root)
{
if (root == NULL)
{
printf("NULL ");
return;
}
else
{
PrevOrder(root->left);
printf("%c ", root->data);
PrevOrder(root->right);
}
}
//后序遍历
void Postorder(BTNode *root)
{
if (root == NULL)
{
printf("NULL ");
return;
}
else
{
printf("%c ", root->data);
PrevOrder(root->left);
PrevOrder(root->right);
}
}
//树结点的个数
int BinaryTreeSize(BTNode *root)
{
return root == NULL ? 0 : BinaryTreeSize(root->left) + BinaryTreeSize(root->right) + 1;
}
//求叶子结点的个数
int BinaryleafSize(BTNode *root)
{
if (root == NULL)
{
return 0;
}
else if(!root->left && !root->right)
{
return 1;
}
else
{
return BinaryleafSize(root->left) + BinaryleafSize(root->right);
}
}
//求二叉树的第k层结点个数
int BinaryKSize(BTNode* root,int k)
{
if (!root)
{
return 0;
}
else if (k == 1)
{
return 1;
}
else
{
return BinaryKSize(root->left, k - 1)
+ BinaryKSize(root->right, k - 1);
}
}
//查找值为val的结点
BTNode* BinaryFind(BTNode* root,char ch)
{
if (!root)
{
return NULL;
}
if (root->data == ch)
{
return root;
}
BTNode* leftNode = BinaryFind(root->left,ch);
BTNode* rightNode = BinaryFind(root->right, ch);
if (leftNode )
{
return leftNode;
}
if(rightNode)
{
return rightNode;
}
return NULL;
}
void TreeLevelorder(BTNode* root)
{
assert(root);
Queue q;
QueueInit(&q);
QueuePush(&q,root);
while (!QueueEmpty(&q))
{
//取出队头的数据
BTNode* front = QueueFront(&q);
QueuePop(&q);
printf("%c ",front->data);
//接着入,出一层父亲结点,带进去子节点
if (front->left != NULL)
{
QueuePush(&q, front->left);
}
if (front->right != NULL)
{
QueuePush(&q, front->right);
}
}
printf("\n");
QueueDestroy(&q);
}
//二叉树的销毁
void BinaryTreeDestroy(BTNode* root)
{
if (!root)
{
return;
}
BinaryTreeDestroy(root->left);
BinaryTreeDestroy(root->right);
free(root);
}
//判断一颗树是不是完全二叉树
bool BinaryTreecomp(BTNode* root)
{
Queue q;
QueueInit(&q);
QueuePush(&q, root);
while (!QueueEmpty(&q))
{
BTNode* front = QueueFront(&q);
QueuePop(&q);
if (!front)
{
break;
}
QueuePush(&q, front->left);
QueuePush(&q, front->right);
}
while (!QueueEmpty(&q))
{
BTNode* front = QueueFront(&q);
if (front)
{
return false;
}
}
return true;
}
我们知道二叉树有三种遍历方式,为了遍历前面构建出来的树型结构这三种遍历方式我们都采用
按照规则,二叉树的遍历有:前序/中序/后序的递归结构遍历:
总结:
//后序遍历
void PrevOrder(BTNode *root)
{
if (root == NULL)
{
printf("NULL ");
return;
}
else
{
PrevOrder(root->left);
PrevOrder(root->right);
printf("%d ",root->data);
}
}
//中序遍历
void Inorder(BTNode *root)
{
if (root == NULL)
{
printf("NULL ");
return;
}
else
{
PrevOrder(root->left);
printf("%d ", root->data);
PrevOrder(root->right);
}
}
//前序遍历
void Postorder(BTNode *root)
{
if (root == NULL)
{
printf("NULL ");
return;
}
else
{
printf("%d ", root->data);
PrevOrder(root->left);
PrevOrder(root->right);
}
}
int BinaryTreeSize(BTNode *root)
{
return root == NULL ? 0 : BinaryTreeSize(root->left)
+ BinaryTreeSize(root->right) + 1;
}
后序思想,递归左右子树,如果该结点为空就返回0,不为空就返回左右子树的结点个数相加的和值 + 1,这里的+ 1 操作是用作计数根结点的(每一个真实结点),其实看作是一个二叉树的后序遍历也不为过
//求叶子结点的个数
int BinaryleafSize(BTNode *root)
{
if (root == NULL)
{
return 0;
}
else if(!root->left && !root->right)
{
return 1;
}
else
{
return BinaryleafSize(root->left)
+ BinaryleafSize(root->right);
}
}
叶子结点表示的是没有孩子的结点,当遍历一颗树不断的往下递归,总会遇到度为0的结点,而这个结点的就是作为这颗树的叶子结点,在这里可以将一颗大树看成是多颗小树,计算出多颗小树的叶子结点个数就是整个大树的叶子结点
//求二叉树的第k层结点个数
int BinaryKSize(BTNode* root,int k)
{
if (!root)
{
return 0;
}
else if (k == 1)
{
return 1;
}
else
{
return BinaryKSize(root->left, k - 1)
+ BinaryKSize(root->right, k - 1);
}
}
想求出第k层的结点的个数只需要将这一层的结点相加得到的结果就是这一层的结点个数
BTNode* BinaryFind(BTNode* root,char ch)
{
if (!root)
{
return NULL;
}
if (root->data == ch)
{
return root;
}
BTNode* leftNode = BinaryFind(root->left,ch);
BTNode* rightNode = BinaryFind(root->right, ch);
if (leftNode )
{
return leftNode;
}
if(rightNode)
{
return rightNode;
}
return NULL;
}
到树的左右子树中去查找该结点如果找到就返回该节点,否则继续查找,直到走到NULL的位置,那就返回NULL
英文缩写为BFS即Breadth FirstSearch。其过程检验来说是对每一层节点依次访问,访问完一层进入下一层,而且每个节点只能访问一次。这里用队列来实现这个遍历方式,还是由于队列先进先出的特性,
实现思路:
先将根入队列,将父亲pop出去后再入孩子,打印父亲的值,那么这一层就已经遍历完了,紧接着就可以继续入下一层,父亲每次pop出去的时让父亲的孩子入队,
void TreeLevelorder(BTNode* root)
{
assert(root);
Queue q;
QueueInit(&q);
QueuePush(&q,root);
while (!QueueEmpty(&q))
{
//取出队头的数据
BTNode* front = QueueFront(&q);
QueuePop(&q);
printf("%c ",front->data);
//接着入,出一层父亲结点,带进去子节点
if (front->left != NULL)
{
QueuePush(&q, front->left);
}
if (front->right != NULL)
{
QueuePush(&q, front->right);
}
}
QueueDestroy(&q);
}
实现思路:后序遍历,从最后一个NULL位置开始边回退,返回它的上一层,释放这个结点
//二叉树的销毁
void BinaryTreeDestroy(BTNode* root)
{
if (!root)
{
return;
}
BinaryTreeDestroy(root->left);
BinaryTreeDestroy(root->right);
free(root);
}
首先我们得有完全二叉树的概念,完全二叉树的最后一层结点个数可以不满,但是必须是从左到右连续的,那么看上面的图,你觉得他会是完全二叉树吗,左边是,右边不是,原因不是连续的,如果接着采用层序遍历的思路搞定这个,还是比较简单的,
//判断一颗树是不是完全二叉树
/**
* struct TreeNode {
* int val;
* struct TreeNode *left;
* struct TreeNode *right;
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* };
*/
class Solution {
public:
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param root TreeNode类
* @return bool布尔型
*/
bool isCompleteTree(TreeNode* root) {
// write code here
if(!root) return false;
queue<TreeNode *> q;
q.push(root);
while(!q.empty()){
auto node = q.front();
q.pop();
if(!node) break;
if(node->left) q.push(node->left);
else q.push(nullptr);
if(node->right) q.push(node->right);
else q.push(nullptr);
}
while(!q.empty()){
auto node = q.front();
if(node != nullptr) return false;
q.pop();
}
return true;
}
};
如果二叉树每个节点都具有相同的值,那么该二叉树就是单值二叉树。只有给定的树是单值二叉树时,才返回 true;否则返回 false
实现思路:
如果左孩子跟右孩子的值都与父亲的值相等,那么他就是单值二叉树,再往下递归的过程中只需要将值不等就直接返回false,否则就继续递归下去直到整个树遍历完了,那么就是单值二叉树
bool isUnivalTree(struct TreeNode* root){
if(!root)
{
return true;
}
//判断左孩子跟父亲是否相等,不等返回false
if(root->left && root->left->val != root->val)
{
return false;
}
//判断右孩子是否和父亲相等,不等返回false
else if(root->right && root->right->val != root->val)
{
return false;
}
//相等继续往下递归,
else
{
return isUnivalTree(root->left)
&& isUnivalTree(root->right);
}
}
给你二叉树的根节点 root ,返回它节点值的 前序 遍历。
实现接口
int* preorderTraversal(struct TreeNode* root,
int* returnSize)
{
}
实现思路:
前序遍历这颗二叉树,将二叉树每个结点的值存放进数组中,最后返回该数组,值得注意的是这个接口的参数,*returnsize,到底需要开辟多大的空间来存放二叉树的值,可以通过遍历二叉树求出它的结点个数,malloc出等大的数组出来,存放结点的值
//计算结点的个数
int TreeSize(struct TreeNode* root)
{
return root == NULL ? 0 : TreeSize(root->left) + TreeSize(root->right) + 1;
}
//以前序遍历的方式,将树的值存放到数组中
void _preoder(struct TreeNode* root,int *retArr, int *pi)
{
if(!root)
{
return;
}
else
{
retArr[(*pi)++] = root->val;
_preoder(root->left,retArr,pi);
_preoder(root->right,retArr,pi);
}
}
int* preorderTraversal(struct TreeNode* root, int* returnSize){
*returnSize = TreeSize(root);
int *retArr = (int *)malloc(sizeof(int) * (* returnSize));
int i = 0;
_preoder(root,retArr,&i);
return retArr;
}
给你两棵二叉树的根节点 p 和 q ,编写一个函数来检验这两棵树是否相同。如果两个树在结构上相同,并且节点具有相同的值,则认为它们是相同的。
实现思路:
能先想到的就是这两颗树都是空树,那么他们就是相同的,还有一种情况就是一个树的结点多,一个树的结点少,少的先被遍历完,所以他们肯定不相同,剩下的就是判断值了,比较两颗树的左右子树的值是否是相等的
bool isSameTree(struct TreeNode* p, struct TreeNode* q){
if(p == NULL && q == NULL)
{
return true;
}
if(p == NULL || q == NULL)
{
return false;
}
else if(p->val != q->val)
{
return false;
}
else
{
return isSameTree(p->left,q->left) && isSameTree(p->right,q->right);
}
}
从树的第二层开始,将每一层的根划分出两颗左右子树,比较根再分别将两颗子树的左孩子和右孩子比较,右孩子和左孩子比较,如果相同就返回true
bool _issymmetry(struct TreeNode *Treeleft, struct TreeNode* Treeright)
{
if(!Treeleft && !Treeright)
{
return true;
}
if(!Treeleft || !Treeright)
{
return false;
}
else if(Treeleft->val != Treeright->val)
{
return false;
}
return _issymmetry(Treeleft->left,Treeright->right)
&& _issymmetry(Treeleft->right,Treeright->left) ;
}
bool isSymmetric(struct TreeNode* root){
if(!root)
{
return true;
}
return _issymmetry(root->left,root->right);
}
题目描述:
翻转一棵二叉树。
实现思路:
递归到最后一层开始再往回返的过程,备份根的左右孩子,回退到根的时候交换左右孩子的位置
struct TreeNode* invertTree(struct TreeNode* root){
if(!root)
return NULL;
struct TreeNode* left = invertTree(root->left);
struct TreeNode* right = invertTree(root->right);
root->left = right;
root->right = left;
return root;
}
给你两棵二叉树 root 和 subRoot 。检验 root 中是否包含和 subRoot 具有相同结构和节点值的子树。如果存在,返回 true ;否则,返回 false。
二叉树 tree 的一棵子树包括 tree 的某个节点和这个节点的所有后代节点。tree 也可以看做它自身的一棵子树。
实现思路:
从root中选出每一个根看作一颗子树去和subroot这颗子树比较,如果他们,左右子树都相等了就返回true,如果不相等继续从root中找下一个根
bool _issymmetry(struct TreeNode *root,
struct TreeNode* subRoot)
{
if(!root && !subRoot)
return true;
if(!root || !subRoot)
return false;
else if(root->val != subRoot->val)
return false;
return _issymmetry(root->left,subRoot->left)
&& _issymmetry(root->right,subRoot->right);
}
bool isSubtree(struct TreeNode* root,
struct TreeNode* subRoot){
if(!root)
return false;
if(_issymmetry(root,subRoot))
return true;
//寻找下一个根比较是否与subRoot相等
return isSubtree(root->left,subRoot)
|| isSubtree(root->right,subRoot);
}
题目描述:
本题中,一棵高度平衡二叉树定义为:一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过 1 。
实现思路:
大问题化成小问题的思路,要想判断是不是平衡二叉树,就得把整个树拆分成多颗子树,去判断左右子树的高度差是否 < 2,分别求出n颗左右子树的深度,如果他们的差距 < 2 就满足,直到把整个树遍历完就返回true,这里采用的遍历方式是后序遍历
bool isbalance(struct TreeNode* root, int *pi)
{
if(!root)
{
*pi = 0;
return true;
}
int leftheight = 0;
if(isbalance(root->left,&leftheight) == false)
return false;
int rightheight = 0;
if(isbalance(root->right,&rightheight) == false)
return false;
*pi = fmax(leftheight,rightheight) + 1;
return abs(leftheight - rightheight) < 2;
}
bool isBalanced(struct TreeNode* root){
if(!root)
return true;
int i = 0;
return isbalance(root,&i);
}
KY11 二叉树遍历
链接: link.
原题描述:
编一个程序,读入用户输入的一串先序遍历字符串,根据此字符串建立一个二叉树(以指针方式存储)。 例如如下的先序遍历字符串: ABC##DE#G##F### 其中“#”表示的是空格,空格字符代表空树。建立起此二叉树以后,再对二叉树进行中序遍历,输出遍历结果。
根据题意手动还原出来的二叉树应该是这样的,满足先序遍历的结构
实现思路:
把字符串存放进一个数组中,每次遍历这个数组,取出一个字符创建结点,从上往下递归,不断创建左右孩子,当遇到#的时候就表示这个结点是叶子,那就返回它的上一层,它的上一层就是根,把叶子当作根的孩子,往上返回,不断创建父子关系,当左子树递归完了就去递归右子树,直到整个树创建出来。
#include<stdio.h>
typedef char BTNodeType;
typedef struct BTNode
{
struct BTNode *left;
struct BTNode *right;
BTNodeType data;
}BTNode;
BTNode *BTNodecreate(char *str,int *pi)
{
if(str[*pi] == '#')
{
(*pi)++;
return NULL;
}
//取字符创建结点
BTNode* root = (BTNode *)malloc(sizeof(BTNode));
root->data = str[(*pi)++];
//创建左右孩子
root->left = BTNodecreate(str, pi);
root->right = BTNodecreate(str, pi);
return root;
}
//中序遍历
void inorder(BTNode *root)
{
if(!root)
{
return ;
}
inorder(root->left);
printf("%c ",root->data);
inorder(root->right);
}
int main()
{
int i = 0;
char arr[100] = {
0};
scanf("%s",arr);
BTNode *root = BTNodecreate(arr,&i);
inorder(root);
return 0;
}
文章浏览阅读3.2k次。本文研究全球与中国市场分布式光纤传感器的发展现状及未来发展趋势,分别从生产和消费的角度分析分布式光纤传感器的主要生产地区、主要消费地区以及主要的生产商。重点分析全球与中国市场的主要厂商产品特点、产品规格、不同规格产品的价格、产量、产值及全球和中国市场主要生产商的市场份额。主要生产商包括:FISO TechnologiesBrugg KabelSensor HighwayOmnisensAFL GlobalQinetiQ GroupLockheed MartinOSENSA Innovati_预计2026年中国分布式传感器市场规模有多大
文章浏览阅读1.1k次,点赞2次,收藏12次。常用组合逻辑电路结构——为IC设计的延时估计铺垫学习目的:估计模块间的delay,确保写的代码的timing 综合能给到多少HZ,以满足需求!_基4布斯算法代码
文章浏览阅读3.3k次,点赞3次,收藏5次。OpenAI Manager助手(基于SpringBoot和Vue)_chatgpt网页版
文章浏览阅读2.2k次。USACO自1992年举办,到目前为止已经举办了27届,目的是为了帮助美国信息学国家队选拔IOI的队员,目前逐渐发展为全球热门的线上赛事,成为美国大学申请条件下,含金量相当高的官方竞赛。USACO的比赛成绩可以助力计算机专业留学,越来越多的学生进入了康奈尔,麻省理工,普林斯顿,哈佛和耶鲁等大学,这些同学的共同点是他们都参加了美国计算机科学竞赛(USACO),并且取得过非常好的成绩。适合参赛人群USACO适合国内在读学生有意向申请美国大学的或者想锻炼自己编程能力的同学,高三学生也可以参加12月的第_usaco可以多次提交吗
文章浏览阅读394次。1.1 存储程序1.2 创建存储过程1.3 创建自定义函数1.3.1 示例1.4 自定义函数和存储过程的区别1.5 变量的使用1.6 定义条件和处理程序1.6.1 定义条件1.6.1.1 示例1.6.2 定义处理程序1.6.2.1 示例1.7 光标的使用1.7.1 声明光标1.7.2 打开光标1.7.3 使用光标1.7.4 关闭光标1.8 流程控制的使用1.8.1 IF语句1.8.2 CASE语句1.8.3 LOOP语句1.8.4 LEAVE语句1.8.5 ITERATE语句1.8.6 REPEAT语句。_mysql自定义函数和存储过程
文章浏览阅读188次。半导体二极管——集成电路最小组成单元。_本征半导体电流为0
文章浏览阅读2.8k次,点赞3次,收藏18次。游戏水面特效实现方式太多。咱们这边介绍的是一最简单的UV动画(无顶点位移),整个mesh由4个顶点构成。实现了水面效果(左图),不动代码稍微修改下参数和贴图可以实现岩浆效果(右图)。有要思路是1,uv按时间去做正弦波移动2,在1的基础上加个凹凸图混合uv3,在1、2的基础上加个水流方向4,加上对雾效的支持,如没必要请自行删除雾效代码(把包含fog的几行代码删除)S..._unity 岩浆shader
文章浏览阅读5k次。广义线性模型是线性模型的扩展,它通过连接函数建立响应变量的数学期望值与线性组合的预测变量之间的关系。广义线性模型拟合的形式为:其中g(μY)是条件均值的函数(称为连接函数)。另外,你可放松Y为正态分布的假设,改为Y 服从指数分布族中的一种分布即可。设定好连接函数和概率分布后,便可以通过最大似然估计的多次迭代推导出各参数值。在大部分情况下,线性模型就可以通过一系列连续型或类别型预测变量来预测正态分布的响应变量的工作。但是,有时候我们要进行非正态因变量的分析,例如:(1)类别型.._广义线性回归模型
文章浏览阅读69次。环境保护、 保护地球、 校园环保、垃圾分类、绿色家园、等网站的设计与制作。 总结了一些学生网页制作的经验:一般的网页需要融入以下知识点:div+css布局、浮动、定位、高级css、表格、表单及验证、js轮播图、音频 视频 Flash的应用、ul li、下拉导航栏、鼠标划过效果等知识点,网页的风格主题也很全面:如爱好、风景、校园、美食、动漫、游戏、咖啡、音乐、家乡、电影、名人、商城以及个人主页等主题,学生、新手可参考下方页面的布局和设计和HTML源码(有用点赞△) 一套A+的网_垃圾分类网页设计目标怎么写
文章浏览阅读614次,点赞7次,收藏11次。之前找到一个修改 exe 中 DLL地址 的方法, 不太好使,虽然能正确启动, 但无法改变 exe 的工作目录,这就影响了.Net 中很多获取 exe 执行目录来拼接的地址 ( 相对路径 ),比如 wwwroot 和 代码中相对目录还有一些复制到目录的普通文件 等等,它们的地址都会指向原来 exe 的目录, 而不是自定义的 “lib” 目录,根本原因就是没有修改 exe 的工作目录这次来搞一个启动程序,把 .net 的所有东西都放在一个文件夹,在文件夹同级的目录制作一个 exe._.net dll 全局目录
文章浏览阅读1.5k次。本文为转载,原博客地址:http://blog.csdn.net/hujingshuang/article/details/46910259简介 BRIEF是2010年的一篇名为《BRIEF:Binary Robust Independent Elementary Features》的文章中提出,BRIEF是对已检测到的特征点进行描述,它是一种二进制编码的描述子,摈弃了利用区域灰度..._breif description calculation 特征点
文章浏览阅读4.1k次,点赞21次,收藏79次。本文是《基于SpringBoot的房屋租赁管理系统》的配套原创说明文档,可以给应届毕业生提供格式撰写参考,也可以给开发类似系统的朋友们提供功能业务设计思路。_基于spring boot的房屋租赁系统论文