【数据结构】二叉树(2)

目录

1. 二叉树的遍历

前序遍历

中序遍历

后序遍历

2. 计算二叉树中的节点个数

3. 计算二叉树中叶子节点个数

4. 计算二叉树的深度

5. 计算二叉树第k层节点个数

6. 二叉树基础练习

7. 二叉树的创建

8. 二叉树的销毁

9. 层序遍历

10. 判断二叉树是否为完全二叉树


1. 二叉树的遍历

二叉树遍历(traversal)是按照一定的次序访问二叉树中的所有节点,并且每个节点仅被访问一次的过程。它是二叉树最基本的运算,是二叉树中所有其他运算实现的基础。

  1. 前序遍历(Preorder Traversal 亦称先序遍历)——访问根结点的操作发生在遍历其左右子树之前。
  2. 中序遍历(Inorder Traversal)——访问根结点的操作发生在遍历其左右子树之中(间)。
  3. 后序遍历(Postorder Traversal)——访问根结点的操作发生在遍历其左右子树之后。

由于被访问的结点必是某子树的根,所以N(Node)、L(Left subtree)和R(Right subtree)又可解释为根、根的左子树和根的右子树。NLR、LNR和LRN分别又称为先根遍历、中根遍历和后根遍历。

前序遍历递归图解:

代码实现

前序遍历

//前序遍历
void PrevOrder(BTNode* root)
{
	if (root == NULL)
	{
		printf("空 ");
		return;
	}
	printf("%d ", root->data);
	PrevOrder(root->left);
	PrevOrder(root->right);
}

中序遍历

//中序遍历
void InOrder(BTNode* root)
{
	if (root == NULL)
	{
		printf("空 ");
		return;
	}	
	InOrder(root->left);
	printf("%d ", root->data);
	InOrder(root->right);
}

后序遍历

//后序遍历
void PostOrder(BTNode* root)
{
	if (root == NULL)
	{
		printf("空 ");
		return;
	}
	PostOrder(root->left);	
	PostOrder(root->right);
	printf("%d ", root->data);
}

以中序遍历为例,递归展开图: 

代码实现: 

#include<stdio.h>
#include<stdlib.h>
typedef int BTDataType;
typedef struct BinaryTreeNode
{
	BTDataType data;//数据元素
	struct BinaryTreeNode* left;//指向左孩子
	struct BinaryTreeNode* right;//指向右孩子
}BTNode;

BTNode* BuyNodee(int x)
{
	BTNode* node = (BTNode*)malloc(sizeof(BTNode));
	if (node == NULL)
	{
		perror("malloc fail");
		return NULL;
	}
	node->data = x;
	node->left = NULL;
	node->right = NULL;

	return node;
}

//创建二叉树
BTNode* CreateBinaryTree()
{
	BTNode* node1 = BuyNodee(1);
	BTNode* node2 = BuyNodee(2);
	BTNode* node3 = BuyNodee(3);
	BTNode* node4 = BuyNodee(4);
	BTNode* node5 = BuyNodee(5);
	BTNode* node6 = BuyNodee(6);
	BTNode* node7 = BuyNodee(7);

	node1->left = node2;
	node1->right = node4;
	node2->left = node3;
	node4->left = node5;
	node4->right = node6;

	return node1;
}

//前序遍历
void PrevOrder(BTNode* root)
{
	if (root == NULL)
	{
		printf("空 ");
		return;
	}
	printf("%d ", root->data);
	PrevOrder(root->left);
	PrevOrder(root->right);
}

//中序遍历
void InOrder(BTNode* root)
{
	if (root == NULL)
	{
		printf("空 ");
		return;
	}	
	InOrder(root->left);
	printf("%d ", root->data);
	InOrder(root->right);
}

//后序遍历
void PostOrder(BTNode* root)
{
	if (root == NULL)
	{
		printf("空 ");
		return;
	}
	PostOrder(root->left);	
	PostOrder(root->right);
	printf("%d ", root->data);
}

int main()
{
	BTNode* root = CreateBinaryTree();
	//前序遍历
	PrevOrder(root);
	printf("\n");
	//中序遍历
	InOrder(root);
	printf("\n");
	//后序遍历
	PostOrder(root);
	printf("\n");

	return 0;
}

运行结果:

2. 计算二叉树中的节点个数

递归思想:

如果二叉树为空,节点个数为0。

如果二叉树不为空,二叉树节点个数=左子树节点个数 + 右子树节点个数 +1

代码实现:

//节点个数
int TreeSize(BTNode* root)
{
	return root == NULL ? 0 :
		TreeSize(root->left) + TreeSize(root->right) + 1;
}

3. 计算二叉树中叶子节点个数

递归思想:

如果二叉树为空,返回0。

如果二叉树不为空,左右子树为空,返回1。

如果二叉树不为空,且左右子树不为空,返回左子树中叶子节点个数加上右子树中叶子节点个数。

代码实现: 

//叶子节点个数
int TreeLeafSize(BTNode* root)
{
	if (root == NULL)
		return 0;
	if (root->left ==NULL && root->right == NULL)
		return 1;
	return TreeLeafSize(root->left) + TreeLeafSize(root->right);
}

4. 计算二叉树的深度

递归思想:

如果二叉树为空,二叉树的深度为0。

如果二叉树不为空,二叉树的深度 = max(左子树深度,右子树深度)+1。 

代码实现: 

//二叉树的深度
int TreeHeight(BTNode* root)
{
	if (root == NULL)
		return 0;
	int height1 = TreeHeight(root->left);
	int height2 = TreeHeight(root->right);
	return height1 > height2 ? height1+1 : height2+1;
}

5. 计算二叉树第k层节点个数

递归思想:

如果二叉树为空,返回0。

如果二叉树不为空且k=1,返回1。

如果二叉树不为空且k>1,返回左子树中k-1层节点个数加右子树中k-1层节点个数。

代码实现:

//计算二叉树第k层节点个数
int TreeLevelKSize(BTNode* root,int k)
{
	if (root == NULL)
		return 0;
	if (k == 1)
		return 1;
	return TreeLevelKSize(root->left, k - 1)
	   + TreeLevelKSize(root->right, k - 1);
}

 在栈中大致过程

6. 二叉树基础练习

题目1 单植二叉树【链接】

题目2 相同的树【链接】

题目3 对称二叉树【链接】

题目4 二叉树的前序遍历【链接】

题目5 二叉树的中序遍历【链接】

题目6 二叉树的后序遍历【链接】

题目7 另一棵树的子树【链接】

7. 二叉树的创建

二叉树的构建及遍历【链接】

代码实现 :

#include <stdio.h>
typedef struct BinaryTreeNode
{
    struct BinaryTreeNode* left;
    struct BinaryTreeNode* right;
    char val;
}BTNode;

BTNode* CreateTree(char*a,char*pi)
{
    if(a[(*pi)]=='#')
    {
        (*pi)++;
        return NULL;
    }   

    BTNode* root=(BTNode*)malloc(sizeof(BTNode));
    root->val=a[(*pi)++];
    root->left=CreateTree(a,pi);
    root->right=CreateTree(a,pi);
        return root;
}

//中序遍历
void InOrder(BTNode* root)
{
	if (root == NULL)
	{		
		return;
	}	
	InOrder(root->left);
	printf("%c ", root->val);
	InOrder(root->right);
}

int main() 
{
   char a[100];
   scanf("%s",a);
   char i=0;
   BTNode* root=CreateTree(a,&i);
   InOrder(root);

    return 0;
}

8. 二叉树的销毁

代码实现:

//二叉树的销毁(后序遍历)
void TreeDestory(BTNode* root)
{
	if (root == NULL)
		return;
	TreeDestory(root->left);
	TreeDestory(root->right);
	free(root);
}

9. 层序遍历

从上到下,从左到右依次将每个数放入到队列中,然后按顺序依次打印就是想要的结果。
1、首先将二叉树的根节点push到队列中,判断队列不为NULL,就输出队头的元素。
2、判断节点是否有孩子,如果有就将孩子push到队列中。

代码实现:

由于要访问每个节点的左右孩子,所以队列的元素类型为节点的指针。Queue.h【链接】

#include"Queue.h"

//层序遍历
void TreeLevelOrder(BTNode* root)
{
	Queue q;
	QueueInit(&q);
	if (root)
		QueuePush(&q, root);
	while (!QueueEmpty(&q))
	{
		BTNode* front = QueueFront(&q);
		QueuePop(&q);

		printf("%d ", front->data);

		if (front->left)
			QueuePush(&q, front->left);
		if (front->right)
			QueuePush(&q, front->right);
	}
	QueueDesTroy(&q);
}

10. 判断二叉树是否为完全二叉树

基本思想:

按照层序遍历,遇到空也进队列,出队列出到空时,就开始判断,后面是全空就是完全二叉树,后面有非空就不是完全二叉树。例:

//判断二叉树是否是完全二叉树
bool TreeComplete(BTNode* root)
{
	Queue q;
	QueueInit(&q);
	if (root)
		QueuePush(&q, root);
	while (!QueueEmpty(&q))
	{
		BTNode* front = QueueFront(&q);
		QueuePop(&q);	
		//遇到第一个空,就可以开始判断,如果队列中还有空,就不是完全二叉树
		if (front == NULL)
		{
			break;
		}

		QueuePush(&q, front->left);		
		QueuePush(&q, front->right);
	}

	while (!QueueEmpty(&q))
	{
		BTNode* front = QueueFront(&q);
		QueuePop(&q);
		if (front)//如果有非空,就不是完全二叉树
		{
			return false;
		}
	}

	QueueDesTroy(&q);
	return true;
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

比特币与区块链原理解析:矿机挖矿与去中心化的未来

✨✨ 欢迎大家来访Srlua的博文&#xff08;づ&#xffe3;3&#xffe3;&#xff09;づ╭❤&#xff5e;✨✨ &#x1f31f;&#x1f31f; 欢迎各位亲爱的读者&#xff0c;感谢你们抽出宝贵的时间来阅读我的文章。 我是Srlua小谢&#xff0c;在这里我会分享我的知识和经验。&am…

StarRocks-join优化

1、背景 有两个大表&#xff0c;都是6kw级别上下的&#xff0c;通过SR然后包装了一个接口对外提供查询&#xff0c;当前的问题是&#xff0c;这样大的join查询会导致BE直接宕机。并且这个sql很有代表性&#xff0c;我截图如下&#xff1a; 这个表是个单分区&#xff0c;所以直接…

Qt中2D绘制系统

目录 一、Qt绘制系统 1.1Qt绘制基本概念 1.2 绘制代码举例 1.3画家 1.3.1 QPainter的工作原理&#xff1a; 1.3.2 自定义绘制饼状图&#xff1a; 1.4画笔和画刷 1.4.1画笔 1.4.2 画刷填充样式 1.5 反走样和渐变 1.6绘制设备 1.7坐标变换 1.8QPainterPath 1.9绘制文…

基于.NET调用WebService服务

基于.NET调用WebService服务 上一篇文章用java的Spring Boot框架搭建了一个WebService服务端&#xff0c;这篇文章通过.NET进行调用&#xff0c;下文基于Visual Studio 2022 引入WebService服务 项目右键 -> 添加 -> 服务引用 选择WCF Web Service&#xff0c;点击下一…

IIC 随机写+多次写 可以控制写几次

verilog module icc_tx#(parameter SIZE 2 , //用来控制写多少次 比如地址是0000 一个地址只能存放8bit数据 超出指针就会到下一个地址0001parameter CLK_DIV 50_000_000 ,parameter SPEED 100_000 ,parameter LED 50 )( input wire c…

微信小程序+Vant-自定义选择器组件(多选

实现效果 无筛选&#xff0c;如有需要可参照单选组件中的方法.json文件配置"component": true,columns需要处理成含dictLabel和dictValue字段&#xff0c;我是这样处理的&#xff1a; let list arr.map(r > {return {...r,dictValue: r.xxxId,dictLabel: r.xxx…

基于边缘智能网关的机房安全监测应用

随着我国工业互联网的扎实推进&#xff0c;越来越多地区积极建设信息基础设施&#xff0c;以充沛算力支撑产业物联网的可持续发展&#xff0c;数据机房就是其中的典型代表。而且随着机房规模的扩大&#xff0c;对于机房的安全管理难题挑战也日益增加。 面向数据机房安全监测与管…

HarmonyOS 应用跨团队 Debug 协作

文章目录 前言案例背景与问题分析问题背景问题分析工具 方法与代码实现前端模块的优化&#xff1a;日志记录与网络监听日志记录代码示例代码解析实现逻辑实际应用场景 网络状态监听代码示例代码解析实现逻辑实际应用场景 后端模块的优化&#xff1a;接口性能与容错机制接口性能…

《UnityShader 入门精要》更复杂的光照

代码&示例图见&#xff1a;zaizai77/Shader-Learn: 实现一些书里讲到的shader 到了这里就开启了书里的中级篇&#xff0c;之后会讲解 Unity 中的渲染路径&#xff0c;如何计算光照衰减和阴影&#xff0c;如何使用高级纹理和动画等一系列进阶内容 Unity 中的渲染路径 在U…

Ubuntu20.04安装kalibr

文章目录 环境配置安装wxPython下载编译测试报错1问题描述问题分析问题解决 参考 环境配置 Ubuntu20.04&#xff0c;python3.8.10&#xff0c;boost自带的1.71 sudo apt update sudo apt-get install python3-setuptools python3-rosinstall ipython3 libeigen3-dev libboost…

P1198 [JSOI2008] 最大数

P1198 [JSOI2008] 最大数https://www.luogu.com.cn/problem/P1198 牵制芝士&#xff1a;单调队列 思路&#xff1a; 我们的任务是找出一个区间最大值的 因为插入的数与上一次的答案有关 所以它是强制在线的&#xff08;真无语了&#xff09; 我们可以在每次插入时整一个叫…

宠物电商对接美团闪购:实现快速配送与用户增值

随着宠物行业的快速发展&#xff0c;宠物电商市场也在不断扩张。消费者的需求不再局限于传统的线上购物模式&#xff0c;越来越多的人开始追求更快捷的配送服务和更优质的购物体验。为了适应这一趋势&#xff0c;许多宠物电商平台开始寻求与本地配送平台合作&#xff0c;以提供…

阿里云oss转发上线-实现不出网钓鱼

本地实现阿里云oss转发上线&#xff0c;全部代码在文末&#xff0c;代码存在冗余 实战环境 被钓鱼机器不出网只可访问内部网络包含集团oss 实战思路 若将我们的shellcode文件上传到集团oss上仍无法上线&#xff0c;那么就利用oss做中转使用本地转发进行上线&#xff0c;先发送…

新型大语言模型的预训练与后训练范式,阿里Qwen

前言&#xff1a;大型语言模型&#xff08;LLMs&#xff09;的发展历程可以说是非常长&#xff0c;从早期的GPT模型一路走到了今天这些复杂的、公开权重的大型语言模型。最初&#xff0c;LLM的训练过程只关注预训练&#xff0c;但后来逐步扩展到了包括预训练和后训练在内的完整…

C#结构体排序(数组)

结构体排序&#xff08;数组&#xff09; 1 示例1.1 以PointF为例展示效果1.2 运行结果展示 2实际运用2.1 创建结构体2.2 调用示例2.3 运行结果展示 1 示例 1.1 以PointF为例展示效果 private void button1_Click(object sender, EventArgs e) {Random random new Random();…

前端高频面试题-并发请求

面试题中&#xff0c;有一道题经常会出现&#xff0c;咱们下面讲一下思路以及写法写一个方法&#xff0c;传入一个请求地址数组&#xff0c;以及一个并发数量&#xff0c;根据并发数量&#xff0c;一起发送请求。如果一个发送完&#xff0c;那么从数组中拿出来一个接着发送&…

RabbitMQ7:消息转换器

欢迎来到“雪碧聊技术”CSDN博客&#xff01; 在这里&#xff0c;您将踏入一个专注于Java开发技术的知识殿堂。无论您是Java编程的初学者&#xff0c;还是具有一定经验的开发者&#xff0c;相信我的博客都能为您提供宝贵的学习资源和实用技巧。作为您的技术向导&#xff0c;我将…

螺旋矩阵(java)

题目描述 给你一个 m 行 n 列的矩阵 matrix &#xff0c;请按照 顺时针螺旋顺序 &#xff0c;返回矩阵中的所有元素。 代码思路&#xff1a; class Solution {public List<Integer> spiralOrder(int[][] matrix) {List<Integer> list new ArrayList<>(); …

Jenkins的使用

文章目录 一、Jenkins是什么\有什么用\与GitLab的对比二、Jenkins的安装与配置Jenkins的安装方式在Linux上安装Jenkins&#xff1a;在Windows上安装Jenkins&#xff1a;配置Jenkins&#xff1a; &#xff08;可选&#xff09;配置启动用户为root&#xff08;一定要是root吗??…

[在线实验]-ActiveMQ Docker镜像的下载与部署

镜像下载 下载ActiveMQ的Docker镜像文件。通常&#xff0c;这些文件会以.tar格式提供&#xff0c;例如activemq.tar。 docker的activemq镜像资源-CSDN文库 加载镜像 下载完成后&#xff0c;您可以使用以下命令将镜像文件加载到Docker中&#xff1a; docker load --input a…