二叉树讲解

目录

前言

二叉树的遍历

层序遍历

队列的代码

 queuepush和queuepushbujia的区别

判断二叉树是否是完全二叉树

前序

中序

后序

功能展示

创建二叉树

初始化

销毁

简易功能介绍

二叉树节点个数

二叉树叶子节点个数

二叉树第k层节点个数

二叉树查找值为x的节点

判断是否为单值二叉数

判断二叉数高度


前言

本文讲解关于二叉树的创建和各种功能的实现,重点讲解前,中,后和层序遍历的写法

(层序遍历放到了本文前面先讲,如果是刚接触二叉数可以先看功能展示)

前中后序的遍历都用到了递归都写法

而层序遍历却不方便,只能创建队列来解决

二叉树的遍历

层序遍历

层序遍历这里重点讲解一下

因为不能使用递归,只好创建队列来帮助实现

队列的代码

头文件

typedef BTNode* QDataType;typedef struct QueueNode
{struct QueueNode* next;QDataType val;
}QNode;typedef struct Queue
{QNode* phead;QNode* ptail;int size;
}Queue;void QueueInit(Queue* pq);
void QueueDestroy(Queue* pq);// 队尾插入
void QueuePush(Queue* pq, QDataType x);
void QueuePushbujia(Queue* pq, QDataType x);
// 队头删除
void QueuePop(Queue* pq);// 取队头和队尾的数据
QDataType QueueFront(Queue* pq);
QDataType QueueBack(Queue* pq);int QueueSize(Queue* pq);
bool QueueEmpty(Queue* pq);

源码

void QueueInit(Queue* pq)
{assert(pq);pq->phead = NULL;pq->ptail = NULL;pq->size = 0;
}void QueueDestroy(Queue* pq)
{assert(pq);QNode* cur = pq->phead;while (cur){QNode* next = cur->next;free(cur);cur = next;}pq->phead = pq->ptail = NULL;pq->size = 0;
}// 队尾插入
void QueuePush(Queue* pq, QDataType x)
{assert(pq);QNode* newnode = (QNode*)malloc(sizeof(QNode));if (newnode == NULL){perror("malloc fail");return;}newnode->next = NULL;newnode->val = x;if (pq->ptail == NULL){pq->phead = pq->ptail = newnode;}else{pq->ptail->next = newnode;pq->ptail = newnode;}pq->size++;
}void QueuePushbujia(Queue* pq, QDataType x)
{assert(pq);QNode* newnode = (QNode*)malloc(sizeof(QNode));if (newnode == NULL){perror("malloc fail");return;}newnode->next = NULL;newnode->val = x;if (pq->ptail == NULL){pq->phead = pq->ptail = newnode;}else{pq->ptail->next = newnode;pq->ptail = newnode;}
}
// 队头删除
void QueuePop(Queue* pq)
{assert(pq);assert(pq->size != 0);/*QNode* next = pq->phead->next;free(pq->phead);pq->phead = next;if (pq->phead == NULL)pq->ptail = NULL;*/// 一个节点if (pq->phead->next == NULL){free(pq->phead);pq->phead = pq->ptail = NULL;}else // 多个节点{QNode* next = pq->phead->next;free(pq->phead);pq->phead = next;}pq->size--;
}QDataType QueueFront(Queue* pq)
{assert(pq);assert(pq->phead);return pq->phead->val;
}QDataType QueueBack(Queue* pq)
{assert(pq);assert(pq->ptail);return pq->ptail->val;
}int QueueSize(Queue* pq)
{assert(pq);return pq->size;
}bool QueueEmpty(Queue* pq)
{assert(pq);return pq->size == 0;
}
 queuepush和queuepushbujia的区别

两个都是将数据尾插进去,但bujia函数并不会对size加加

这样我们不仅可以正常打印N还不影响真实数据的打印

void BinaryTreeLevelOrder(BTNode* root)
{assert(root);Queue a;QueueInit(&a);BTNode* n = BuyNode1(root->_data);n = root;BTNode* null = BuyNode1('N');printf("%c ", n->_data);while (1){if (n->_left != NULL){QueuePush(&a, n->_left);}else{QueuePushbujia(&a,null);}if (n->_right != NULL){QueuePush(&a, n->_right);}else{QueuePushbujia(&a,null);}if (QueueEmpty(&a)){break;}n = QueueFront(&a);QueuePop(&a);if (n->_data == 'N'){a.size++;}printf("%c ", n->_data);}
}

每拿出一个头数据时就会对size--这样的话如果为N的话很有可能会出现size减完了但实际数据没有打印完的情况

所以这里加入了判断n->_data等于N时应该让size++ 

利用写出来的层序遍历就可以实现

判断二叉树是否是完全二叉树

i和x的作用

如果是完全二叉树遇到一个N后不可能再遇到N意外的数了

否则就是非完全二叉树

利用这一特征

当遇到第一个N时让i++

如果i不等于0说明遇到过N了如果此时遇到了非N的数那么就让n++

如果两个数同时不为0则为非完全二叉树

int BinaryTreeComplete(BTNode* root)
{assert(root);Queue a;QueueInit(&a);BTNode* n = BuyNode1(root->_data);n = root;BTNode* null = BuyNode1('N');//printf("%c ", n->_data);char pan = 'x';int i = 0;int x = 0;while (1){if (n->_left != NULL){QueuePush(&a, n->_left);}else{QueuePushbujia(&a, null);}if (n->_right != NULL){QueuePush(&a, n->_right);}else{QueuePushbujia(&a, null);}if (QueueEmpty(&a)){break;}n = QueueFront(&a);QueuePop(&a);if (n->_data == 'N'){a.size++;}//printf("%c ", n->_data);pan = n->_data;if (pan == 'N'){i++;}if (i !=0){if (pan != 'N'){x++;}}if (i!=0&&x!=0){return 1;}}return 0;
}

前序

void BinaryTreePrevOrder(BTNode* root)
{if (root == NULL){printf("N ");return;}printf("%c ", root->_data);BinaryTreePrevOrder(root->_left);BinaryTreePrevOrder(root->_right);
}

中序

void BinaryTreeInOrder(BTNode* root)
{if (root == NULL){printf("N");return;}BinaryTreeInOrder(root->_left);printf("%c ", root->_data);BinaryTreeInOrder(root->_right);
}

后序

void BinaryTreePostOrder(BTNode* root)
{if (root == NULL){printf("N");return;}BinaryTreePostOrder(root->_left);BinaryTreePostOrder(root->_right);printf("%c ", root->_data);
}

功能展示

完成关于二叉树的如下功能

//初始化
BTNode* BuyNode1(BTDataType x);// 通过前序遍历的数组"ABD##E#H##CF##G##"构建二叉树
BTNode* BinaryTreeCreate(BTDataType* a, int n, int* pi);
// 二叉树销毁
void BinaryTreeDestory(BTNode** root);
// 二叉树节点个数
int BinaryTreeSize(BTNode* root);
// 二叉树叶子节点个数
int BinaryTreeLeafSize(BTNode* root);
// 二叉树第k层节点个数
int BinaryTreeLevelKSize(BTNode* root, int k);
// 二叉树查找值为x的节点
BTNode* BinaryTreeFind(BTNode* root, BTDataType x);
// 二叉树前序遍历 
void BinaryTreePrevOrder(BTNode* root);
// 二叉树中序遍历
void BinaryTreeInOrder(BTNode* root);
// 二叉树后序遍历
void BinaryTreePostOrder(BTNode* root);
// 层序遍历
void BinaryTreeLevelOrder(BTNode* root);
// 判断二叉树是否是完全二叉树
int BinaryTreeComplete(BTNode* root);
//判断是否为单值二叉数
bool isUnivalTree(struct BTNode* root);
//判断二叉数高度
int maxDepth(struct BTNode* root);

创建二叉树

手动创建一个二叉树可以让后面的功能更方便调试

首先确定结构体内容如下

typedef char BTDataType;typedef struct BinaryTreeNode
{BTDataType _data;struct BinaryTreeNode* _left;struct BinaryTreeNode* _right;
}BTNode;

在进行手动创建一个二叉树

创建之前需要初始化结构体

初始化

//初始化
BTNode* BuyNode1(BTDataType x)
{BTNode* n = (BTNode*)malloc(sizeof(BTNode));if (n == NULL){perror("malloc false");return NULL;}n->_data = x;n->_left = NULL;n->_right = NULL;return n;
}

有了初始化代码就可以正式创建二叉树了 

BTNode* headadd()
{BTNode* a1 = BuyNode1('a');BTNode* a2 = BuyNode1('b');BTNode* a3 = BuyNode1('c');BTNode* a4 = BuyNode1('d');BTNode* a5 = BuyNode1('e');a1->_left = a2;a1->_right = a3;a2->_left = a4;a4->_right = a5;return a1;
}

此时二叉树就建好了

有了初始化就需要有销毁,防止内存泄漏

销毁

使用递归思想比较方便

void BinaryTreeDestory(BTNode** root)
{assert(root);assert(*root);BinaryTreeDestory(&((*root)->_left));BinaryTreeDestory(&((*root)->_right));free(*root);*root == NULL;
}

简易功能介绍

大多数采用递归的方法即可轻松解决

二叉树节点个数

int BinaryTreeSize(BTNode* root)
{if (root == NULL){return 0;}return 1+BinaryTreeSize(root->_left)+BinaryTreeSize(root->_right);

二叉树叶子节点个数
 

int BinaryTreeLeafSize(BTNode* root)
{if (root == NULL){return 0;}if (root->_left == NULL && root->_right == NULL){return 1;}return BinaryTreeLeafSize(root->_left) + BinaryTreeLeafSize(root->_right);
}

二叉树第k层节点个数
 

int BinaryTreeLevelKSize(BTNode* root, int k)
{if (root == NULL||k<1){return 0;}if (root!=NULL&&k == 1){return 1;}return BinaryTreeLevelKSize(root->_left, k - 1) +BinaryTreeLevelKSize(root->_right, k - 1);
}

二叉树查找值为x的节点
 

BTNode* BinaryTreeFind(BTNode* root, BTDataType x)
{if (root == NULL){return NULL;}if (root->_data == x){return root;}BTNode* lf = BinaryTreeFind(root->_left, x);if (lf != NULL){return lf;}BTNode* lr = BinaryTreeFind(root->_right, x);if (lr != NULL){return lr;}return NULL;
}

判断是否为单值二叉数

bool isUnivalTree(BTNode* root) 
{if (root == NULL){return true;}if (root->_left){if (root->_data!= root->_left->_data){return false;}}if (!isUnivalTree(root->_left)){return false;}if (root->_right){if (root->_data != root->_right->_data){return false;}}if (!isUnivalTree(root->_right)){return false;}return true;
}

判断二叉数高度

int maxDepth(BTNode* root)
{if (root == NULL){return 0;}int leftsize = maxDepth(root->_left);int rightsize = maxDepth(root->_right);return leftsize > rightsize ? leftsize + 1 : rightsize + 1;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/22521.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

自动驾驶仿真:python和carsim联合仿真案例

文章目录 前言一、Carsim官方案例二、Carsim配置1、车辆模型2、procedure配置3、Run Control配置 三、python编写四、运行carsim五、运行python总结 前言 carsim内部有许多相关联合仿真的demo&#xff0c;simulink、labview等等都有涉及&#xff0c;这里简单介绍下python和car…

stm32编译原理

STM32编译原理主要包括以下几个方面&#xff1a; &#xff08;1&#xff09;编译器选择&#xff1a;STM32可以使用多种编译器进行开发&#xff0c;如Keil、IAR、GCC等。不同的编译器有不同的特点和优缺点&#xff0c;需要根据具体需求进行选择。 &#xff08;2&#xff09;编…

vuInhub靶场实战系列-DC-9实战

免责声明 本文档仅供学习和研究使用,请勿使用文中的技术源码用于非法用途,任何人造成的任何负面影响,与本人无关。 目录 免责声明前言一、环境配置二、信息收集2.1 主机发现2.2 端口扫描2.3 指纹识别2.4 目录扫描2.4.1 Nikto目录扫描2.4.2 dirsearch目录扫描 2.5 漏洞发现2.5.…

webpack怎么配置单页面或者多页面项目?

单页直接在entry中指定单页面的入口文件即可&#xff0c;对于多页面来说&#xff0c;如果页面之间有依赖关系可以考虑将entry的值改成一个数组&#xff0c;数组中的每一项是入口文件的地址&#xff0c;并且通过dependOn配置多个入口的依赖关系&#xff0c;一般的&#xff0c;我…

OTTO、亚马逊、Temu卖家如何运用测评补单来提高购买率?

在跨境电商的广阔舞台上&#xff0c;测评补单无疑是一股不可或缺的强劲动力。商家们深知&#xff0c;通过补单这一手段&#xff0c;能够快速为产品注入活力&#xff0c;使销量迅猛攀升&#xff0c;评论如潮涌至&#xff0c;进而在激烈的竞争中脱颖而出&#xff0c;勇攀销量之巅…

绘画新手必备!六款免费易用的绘图软件推荐

在当今的数字世界里有各种各样的设计创作工具&#xff0c;那么问题来了我们应该如何在众多免费绘图软件中选择呢&#xff1f;为了回答这个问题&#xff0c;我们将在本文中介绍和测评六个领先的绘图软件。每一个都有自己独特的特点和优势&#xff0c;适合不同的需求和用户。以下…

香港优才计划是什么?一文说明白2024香港优才政策、申请条件、流程及利弊

香港优才计划是拿香港身份比较热门的方式之一&#xff0c;对很多想要保留生活重心在内地&#xff0c;但是又需要香港身份为子女规划教育升学的人来说&#xff0c;申请香港优才计划是获取香港身份再好不过的方式。 我们刚开始了解香港优才计划可能会有各种各样的担心&#xff0…

Terraform安装+部署Azure Resource笔记

安装 下载 Terraform&#xff1a; 首先&#xff0c;访问 官方 Terraform 网站。找到适用于 Windows 的 Terraform 包&#xff0c;并下载 zip 文件。解压 Terraform 包&#xff1a; 将下载的 zip 文件解压到一个新文件夹中&#xff0c;命名为 “Terraform”。可以选择任何位置作…

IDC最新报告:预计到2027年全球数字化转型支出将近4万亿美元

根据国际数据公司&#xff08;IDC&#xff09;5月30日发布的《全球数字化转型支出指南》&#xff0c;预计到2027年全球数字化转型&#xff08;DX&#xff09;支出将接近4万亿美元。在人工智能&#xff08;AI&#xff09;和生成式人工智能&#xff08;Generative AI&#xff09;…

手机自动化测试笔记:1.appium的安装与使用

建议先安装前置的程序&#xff0c;同时建议使用anconda进行环境管理。 参考1&#xff1a; 深度学习笔记&#xff1a;1.anaconda安装-CSDN博客https://blog.csdn.net/weixin_42771529/article/details/139434840 参考2&#xff1a; 笔记&#xff1a;如何在pycharm中使用anaco…

EyeGlassesGAN——通过消除人脸所带的眼镜以提高人脸识别的精度

0. 引言 从人脸图像中自动去除眼镜的框架是一个具有挑战性的问题&#xff0c;因为它涉及到精确地识别和处理图像中的眼镜以及相关的眩光和有色镜片。以下是该论文可能提出的一些关键点&#xff1a; &#xff08;1&#xff09;. 学习框架&#xff1a; 数据集构建&#xff1a;…

深入浅出mysql海量数据批量更新插入、批量查询

1. mysql的批量写 mysql 批量插入可以用下面这种&#xff0c;在values 之后跟上各种多个值列表。但这种写法可能导致sql长度超长、锁超时等问题。 insert into (field1,field1,field1,) values (value01,value02,value03),(value11,value12,value13),(value21,value22,value2…

力扣1493.删掉一个元素以后全为1

力扣1493.删掉一个元素以后全为1 单调队列&#xff1a;找到一个最多1个0的子数组 最终结果为该子数组长度-1 特判如果数组全0&#xff0c;return 0 class Solution {public:int longestSubarray(vector<int>& nums) {int res0,sum0;for(int i0,j0;i<nums.size(…

Kotlin 异常处理

文章目录 什么是异常抛出异常通过异常信息解决异常捕获异常 什么是异常 我们在运行程序时&#xff0c;如果代码出现了语法问题或逻辑问题&#xff0c;会导致程序编译失败或退出&#xff0c;称为异常。运行结果会给出一个一长串的红色字&#xff0c;通常会给出异常信息&#xf…

使用springboot+vue实现阿里云oss上传

一、前言 我们后端开发中&#xff0c;时常需要用到文件上传的功能&#xff0c;无非是保存到服务器本地或者如阿里云、七牛云这种云存储的方案。本篇介绍一种使用后台springboot结合前端vue实现阿里云oss上传的功能。 二、实现过程 前端实现一个通用的上传组件UploadFile &l…

可以通过其瞳孔判断AI生成的人脸数据是否可靠

概述 我们都知道&#xff0c;GANs的发展使得生成相互之间无法区分的人脸图像成为可能。虽然这项技术在发展&#xff0c;但也有弊端&#xff0c;比如出现了用生成的人脸作为资料图片的虚假社交媒体账户。因此&#xff0c;随着GANs的发展&#xff0c;使用深度学习模型检测生成的…

python中有时使用pip安装库而有时又使用conda安装库,到底应该使用哪个管理工具进行库的安装呀?

决定使用conda还是pip来安装Python库主要基于以下几个因素&#xff1a; 库的可用性&#xff1a; Conda&#xff1a;如果你要安装的库在Anaconda的默认频道或conda-forge等其他Conda频道中存在&#xff0c;优先使用conda install。Conda不仅管理Python包&#xff0c;还能管理非…

Java Web学习笔记5——基础标签和样式

<!DOCTYPE html> html有很多版本&#xff0c;那我们应该告诉用户和浏览器我们现在使用的是HMTL哪个版本。 声明为HTML5文档。 字符集&#xff1a; UTF-8&#xff1a;现在最常用的字符编码方式。 GB2312&#xff1a;简体中文 BIG5&#xff1a;繁体中文、港澳台等方式…

Ubuntu的基本使用(ROS)

Ubuntu的基本使用&#xff08;ROS&#xff09; 终端常用指令 1. ls - 列出目录内容 用途&#xff1a;显示当前目录下的文件和文件夹。示例&#xff1a; ls&#xff1a;列出当前目录下的所有文件和文件夹。ls -l&#xff1a;以列表形式显示更详细的信息&#xff08;如权限、所…

ARM32开发——串口输出

&#x1f3ac; 秋野酱&#xff1a;《个人主页》 &#x1f525; 个人专栏:《Java专栏》《Python专栏》 ⛺️心若有所向往,何惧道阻且长 文章目录 需求串口数据发送串口打印实现复用功能串口发送流程&#xff08;了解&#xff09;串口的标志位关心的内容 需求 串口循环输出内容到…