二叉树的实现(详解,数据结构)

news2025/1/12 15:59:34

目录

一,二叉树需要实现的功能

二,下面是各功能详解

0.思想:

1.创建二叉树结点:

2.通过前序遍历的数组"ABD##E#H##CF##G##"构建二叉树

3.二叉树销毁:

4.前序遍历:

5.中序遍历:

6.后序遍历:

 7.层序遍历:

1.先实现队列的基本功能:

2.基于队列实现层序:

8.计算各类结点数量:

1.计算二叉树结点数量:

2.计算叶子结点数量:

3.计算K层结点数量:

9.二叉树查找值为X的结点:

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


一,二叉树需要实现的功能

// 通过前序遍历的数组"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);

二,下面是各功能详解

0.思想:

下面很多功能都涉及分治的思想(分治法是算法常用的解题方法之一,是将一个大的问题拆分为若干小的问题。)

1.创建二叉树结点:

//重命名存储变量类型,方便更改
typedef char BTDataType;

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

2.通过前序遍历的数组"ABD##E#H##CF##G##"构建二叉树

// 通过前序遍历的数组"ABD##E#H##CF##G##"构建二叉树
BTNode* BinaryTreeCreate(BTDataType* a, int n, int* pi) {
	if (*pi >= n || a[*pi] == '#') {
		(*pi)++;
		return NULL;
	}
	BTNode* Node = (BTNode*)malloc(sizeof(BTNode));
	if (Node == NULL) {
		perror("BinaryTreeCreate::malloc");
		exit(0);
	}
	Node->_data = a[*pi];
	(*pi)++;
	Node->_left = BinaryTreeCreate(a, n, pi);
	Node->_right = BinaryTreeCreate(a, n, pi);
	return Node;
}

按照以上所给数组描述,我们创建出的二叉树:

3.二叉树销毁:

二叉树的存储类似链表,可以由前面的结点找到后面的结点,因此二叉树的销毁也是由后向前销毁会方便很多,所以我们采取后序来销毁二叉树

// 二叉树销毁
void BinaryTreeDestory(BTNode** root) {
	if (*root == NULL) {
		return;
	}
	BinaryTreeDestory(&(*root)->_left);
	BinaryTreeDestory(&(*root)->_right);
	free(*root);
	*root = NULL;
}

4.前序遍历:

        i、先访问根结点;

        ii、再前序遍历左子树;

        iii、最后前序遍历右子树;

算法实现:

// 二叉树前序遍历 
void BinaryTreePrevOrder(BTNode* root) {
	if (root != NULL) {
		printf("%c ", root->_data);
		BinaryTreePrevOrder(root->_left);
		BinaryTreePrevOrder(root->_right);
	}
}

5.中序遍历:

        i、中序遍历左子树;

        ii、访问根结点;

        iii、中序遍历右子树

算法实现:

// 二叉树中序遍历
void BinaryTreeInOrder(BTNode* root) {
	if (root != NULL) {
		BinaryTreeInOrder(root->_left);
		printf("%c ", root->_data);
		BinaryTreeInOrder(root->_right);
	}
}

6.后序遍历:

        i、后序遍历左子树

        ii、后序遍历右子树

        iii、访问根结点

 算法实现:

// 二叉树后序遍历
void BinaryTreePostOrder(BTNode* root) {
	if (root != NULL) {
		BinaryTreePostOrder(root->_left);
		BinaryTreePostOrder(root->_right);
		printf("%c ", root->_data);
	}
}

 7.层序遍历:

设二叉树的根节点所在层数为1,层序遍历就是从所在二叉树的根节点出发,首先访问第一层的树根节点,然后从左到右访问第2层上的节点,接着是第三层的节点,以此类推,自上而下,自左至右逐层访问树的结点的过程就是层序遍历。

思路:层序遍历需要用到队列的知识,就是先将根结点入队,判断队列是否为空,循环将队首元素出队的同时队首元素子节结点入队

算法实现:

1.先实现队列的基本功能:
typedef BTNode QDataType;
// 链式结构:表示队列 
typedef struct QListNode
{
	struct QListNode* _next;
	QDataType* _data;
}QNode;
// 队列的结构 
typedef struct Queue
{
	QNode* _front;
	QNode* _rear;
}Queue;
// 初始化队列 
void QueueInit(Queue* q) {
	assert(q);
	q->_front = NULL;
	q->_rear = NULL;
}
int QueueEmpty(Queue* q);
// 队尾入队列 
void QueuePush(Queue* q, QDataType* data) {
	assert(q);
	QNode* tmp = (QNode*)malloc(sizeof(QNode));
	if (tmp == NULL) {
		perror("QueuePush:malloc");
		return;
	}
	tmp->_data = data;
	tmp->_next = NULL;
	if (QueueEmpty(q)) {
		q->_front = tmp;
		q->_rear = tmp;
	}
	q->_rear->_next = tmp;
	q->_rear = tmp;
}
// 队头出队列 
void QueuePop(Queue* q) {
	if (QueueEmpty(q)) {
		printf("Pop: Queue is empty\n"); // 更清晰的错误信息  
		exit(0);
	}
	q->_front = q->_front->_next;
	//free(tmp);
}
// 获取队列头部元素 
QDataType* QueueFront(Queue* q) {
	return q->_front->_data;
}
// 获取队列队尾元素 
QDataType* QueueBack(Queue* q) {
	return q->_rear->_data;
}
// 获取队列中有效元素个数 
int QueueSize(Queue* q) {
	QNode* cur = q->_front;
	int size = 0;
	while (cur) {
		size++;
		cur = cur->_next;
	}
	return size;
}
// 检测队列是否为空,如果为空返回非零结果,如果非空返回0 
int QueueEmpty(Queue* q) {
	assert(q);
	if (q->_front == NULL) {
		return 1;
	}
	return 0;
}
// 销毁队列 
void QueueDestroy(Queue* q) {
	assert(q);
	while (!QueueEmpty(q)) {
		QueuePop(q);
	}
}
2.基于队列实现层序:
// 层序遍历
void BinaryTreeLevelOrder(BTNode* root) {
	Queue* queue = (Queue*)malloc(sizeof(Queue));
	BTNode* front;
	QueueInit(queue);
	if (root) {
		QueuePush(queue, root);
	}
	while (!QueueEmpty(queue)) {
		front = QueueFront(queue);
		if (front->_left)
		{
			QueuePush(queue, front->_left);
		}
		if (front->_right)
		{
			QueuePush(queue, front->_right);
		}
		printf("%c ",front->_data);
		QueuePop(queue);
	}
	printf("\n");
	QueueDestroy(queue);
}

8.计算各类结点数量:

1.计算二叉树结点数量:
// 二叉树节点个数
int BinaryTreeSize(BTNode* root) {
	if (root == NULL) {
		return 0;
	}
	else {
		return BinaryTreeSize(root->_left) + BinaryTreeSize(root->_right) + 1;
	}
}
2.计算叶子结点数量:
// 二叉树叶子节点个数
int BinaryTreeLeafSize(BTNode* root) {
	if (root == NULL) {
		return 0;
	}
	if (root->_left == NULL && root->_right == NULL) {
		return 1;
	}
	else {
		return BinaryTreeLeafSize(root->_left) + BinaryTreeLeafSize(root->_right);
	}
}
3.计算K层结点数量:
// 二叉树第k层节点个数
int BinaryTreeLevelKSize(BTNode* root, int k) {
	if (root == NULL) {
		return 0;
	}
	if (k == 1) {
		return 1;
	}
	return BinaryTreeLevelKSize(root->_left, k - 1) + BinaryTreeLevelKSize(root->_right, k - 1);
}

9.二叉树查找值为X的结点:

// 二叉树查找值为x的节点
BTNode* BinaryTreeFind(BTNode* root, BTDataType x) {
	if (root==NULL) {
		return NULL;
	}
	if (root->_data == x) {
		return root;
	}
	BTNode* r1 = BinaryTreeFind(root->_left, x);
	if (r1 != NULL) {
		return r1;
	}
	return BinaryTreeFind(root->_right, x);
}

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

根据完全二叉树的定义,具有n个结点的完全二叉树与满二叉树中编号从1~n的结点一一对应。
算法思想:采用层次遍历算法,将所有结点加入队列(包括空结点)。遇到空结点时,查看其后是否有非空结点。若有,则二叉树不是完全二叉树。

判断二叉树是否为完全二叉树是二叉树层序遍历的基本用途之一,也要借助队列来实现;

算法实现:

// 判断二叉树是否是完全二叉树
int BinaryTreeComplete(BTNode* root) {
	Queue queue;
	QueueInit(&queue);
	if (root) {
		QueuePush(&queue, root);
	}
	while (!QueueEmpty(&queue)) {
		BTNode* front = QueueFront(&queue);
		QueuePop(&queue);
		if (front == NULL) {
			break;
		}
		QueuePush(&queue, front->_left);
		QueuePush(&queue, front->_right);
	}
	while (!QueueEmpty(&queue)) {
		BTNode* front = QueueFront(&queue);
		QueuePop(&queue);
		if (front) {
			QueueDestroy(&queue);
			return 0;
		}
	}
	QueueDestroy(&queue);
	return 1;
}

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

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

相关文章

QT5之布局操作

目录 实验之前的前提 局部布局和整体布局定义 快捷工具 水平和垂直布局 水平布局 在对象区域可以看出三个已经被水平布局在一起 在对象区域选中布局,点击工具取消当前布局 可以将两个小局部进行大局部布局 网格布局 弹簧布局 分割器布局 器件对齐边距 也…

Java Map集合(一)

1. Map接口 1.1 Map接口概述 Map接口是一种双列集合。Map的每个元素都包含一个键对象Key和一个值对象Value ,键对象和值对象之间存在对应关系,这种关系称为映射(Mapping)。 Map接口中的元素,可以通过 key 找到 value&…

STD10A230XCB电源模块STD05A230XCB整流模块介绍

STD10A230XCB电源模块STD05A230XCB整流模块介绍,直流屏电源模块STD05A230XCB,整流模块STD10A115XCB,STD20A115XCB,STD10A230X,STD05A230X,直流屏充电模块的关键词: 电力智能高频开关充电模块STD20A230XCB,高…

这是一个简单的照明材料网站,后续还会更新

1、首页效果图 代码 <!DOCTYPE html> <html><head><meta charset"utf-8" /><title>爱德照明网站首页</title><style>/*外部样式*/charset "utf-8";*{margin: 0;padding: 0;box-sizing: border-box;}a{text-dec…

Golang Colly爬取图片gorm存储数据

语言:Golang 库:Iris/Colly/gorm 运行结果 text/html; charset=utf-8 It is image 20240429222029_0_0.jpg Saved file: images\20240429222029_0_0.jpg text/html; charset=utf-8 It is image 20240429222030_1_0.jpg Saved file: images\20240429222030_1_0.jpg It is ima…

遭遇“U盘只剩USBC乱码”危机?这里有你需要的解决方案!

当你满心期待地将U盘插入电脑&#xff0c;准备读取或传输文件时&#xff0c;突然发现U盘中的文件名全部变成了乱码&#xff0c;尤其是当这些乱码以“USBC”开头时&#xff0c;你可能会感到惊慌失措。这种情况不仅影响你的工作效率&#xff0c;还可能导致重要数据的丢失。那么&a…

一键解决!Microsoft VB/VC 微软常用运行库全版本整合包组件可选 v240329

01 软件介绍 众多程序的正常运行&#xff0c;依赖于微软的运行库。而运行库包括多种类型&#xff0c;如VB&#xff08;Visual Basic&#xff09;和VC&#xff08;Visual C&#xff09;&#xff0c;并且涵盖了不同的版本。鉴于此&#xff0c;整合版的运行库合集提供了一种高效的…

修改 Windows 服务器远程端口,以阿里云服务器 ECS 为例

一、WinR - mstsc.exe 登录远程服务器 二、WinR - regedit.exe 打开注册表 三、打开注册表 tcp 路径&#xff1a; 计算机\HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\TerminalServer\Wds\rdpwd\Tds\tcp 双击右侧 PortNumber 子健&#xff0c;勾选十进制&a…

每日一题(AL001):A+B Format--字符串处理

找输出的顺序很重要&#xff1a; #include<bits/stdc.h> using namespace std; int main(){int a,b;cin>>a>>b;int sumab;if(sum0) cout<<0;bool ftrue;vector<char> v;if(sum<0) {ffalse; sum-sum;}while(sum>0){char cstatic_cast<c…

知识图谱推动条件

文章目录 计算设备及硬件的发展可用数据规模的提升算法演进数据/知识检索需求攀升开源知识库建设专业人才培养 计算设备及硬件的发展 知识图谱的发展离不开计算硬件的支撑&#xff0c;特别是知识图谱构建、推理、应用过程中的机器学习算法的训练和预测等过程&#xff0c;对计算…

《网络安全技术 网络安全众测服务要求》

近日&#xff0c;全国网络安全标准化技术委员会发布《网络安全技术 网络安全众测服务要求》&#xff08;GB/T 43741-2024&#xff0c;以下简称“众测服务要求”&#xff09;&#xff0c;并将在2024年11月1日正式实施。 《众测服务要求》确立了网络安全众测服务的角色及其职责&…

二维偏序 + LIS, CF 1575L Longest Array Deconstruction

目录 一、题目 1、题目描述 2、输入输出 2.1输入 2.2输出 3、原题链接 二、解题报告 1、思路分析 2、复杂度 3、代码详解 一、题目 1、题目描述 2、输入输出 2.1输入 2.2输出 3、原题链接 Problem - 1575L - Codeforces 二、解题报告 1、思路分析 我们考虑最终 …

C语言零基础快速入门视频教程

C语言零基础快速入门视频教程 介绍C语言C语言零基础视频教程领取教程下期更新预报 介绍C语言 C语言零基础快速入门&#xff1a;探索C语言的起源、特性与魅力 在编程世界中&#xff0c;C语言犹如一座古老而坚实的桥梁&#xff0c;连接着计算机科学的过去与现在。作为一门历史悠…

Flutter笔记:Widgets Easier组件库(10)快速处理承若型对话

Flutter笔记 使用Widgets Easier组件库快速处理承若型对话 - 文章信息 - Author: 李俊才 (jcLee95) Visit me at CSDN: https://jclee95.blog.csdn.netMy WebSite&#xff1a;http://thispage.tech/Email: 291148484163.com. Shenzhen ChinaAddress of this article:https://…

ApiHug 官方站点

&#x1f917; ApiHug {Postman|Swagger|Api...} 快↑ 准√ 省↓ GitHub - apihug/apihug.com: All abou the Apihug apihug.com: 有爱&#xff0c;有温度&#xff0c;有质量&#xff0c;有信任ApiHug - API design Copilot - IntelliJ IDEs Plugin | Marketplacehttps://…

[数据结构]——非递归排序总结——笔试爱考

具体代码实现在gitee&#xff1a;登录 - Gitee.com 目录 具体代码实现在gitee&#xff1a;登录 - Gitee.com 1.非递归实现的快速排序算法。 第一步 首先要创建一个栈 第二步紧接着进行入栈&#xff0c;出栈&#xff0c;弹出栈顶元素&#xff0c;获取栈顶元素&#xff0c;判…

多模态大语言模型和 Apple 的 MM1

原文地址&#xff1a;multimodal-large-language-models-apples-mm1 2024 年 4 月 13 日 抽象是计算机科学中最关键的概念之一&#xff0c;具有一些最强大的影响。从简单的角度来看&#xff0c;抽象就是将某一事物应用于多种不同情况的能力。例如&#xff0c;如果你创造了一种…

【C++】:类和对象(下)

目录 一&#xff0c;再谈构造函数1.初始化列表2. 隐式类型转换的过程及其优化3. 隐式类型转换的使用4. explcit关键字5. 单参数和多参数构造函数的隐式类型转换 二&#xff0c;static成员1.静态成员变量2.静态成员函数3. static 成员的应用 三&#xff0c;友元3.1 友元函数3.2 …

Colab - Introduction to Object Detection using TensorFlow Hub

Colab - Introduction to Object Detection using TensorFlow Hub 1. 源由2. TensorFlow Hub3. 目标检测3.1 举例 - EfficientDet/D4 COCO 20173.2 下载示例图像3.2.1 显示部分样本3.2.2 定义一个将类别ID映射到类别名称和颜色的字典 3.3 加载模型3.4 单张照片执行推理3.4.1 推…

网络基础(全)

协议 ”协议“就是一种约定。那么协议需要需要管理吗&#xff1f;答案是当然需要管理呀。 操作系统要进行协议管理——先描述&#xff0c;在组织协议本质就是软件&#xff0c;软件是可以进分层的协议在设计的时候&#xff0c;就是被层状的划分的为什么要划分为层状结呢&#…