数组结构:链式结构二叉树

news2024/9/22 5:36:54

1.实现链式结构二叉树

用链表来表示一棵二叉树,即用链来指示元素的逻辑关系。通常的方法是链表中每个结点由三个域组成,数据域和左右指针域,左右指针分别用来给结点的左孩子和右孩子所在的链结点的存储地址,其结构如下:

//定义二叉树的链式结构
typedef int BTDataType;
typedef struct BinaryTreeNode
{
	BTDataType data;
	struct BinaryTreeNode* left;
	struct BinaryTreeNode* right;
}BTNode;

二叉树的创建方式比较复杂,为了更好的步入到二叉树内容中,我们先手动创建一棵链式二叉树。


BTNode* BuyNode(BTDataType x)
{
	BTNode* newnode = (BTNode*)malloc(sizeof(BTNode));
	if (newnode == NULL)
	{
		perror("malloc fail!");
		exit(1);
	}
	newnode->data = x;
	newnode->left = newnode->right = NULL;

	return newnode;
}
void CreatTree()
{
	BTNode* node1 = BuyNode(1);
	BTNode* node2 = BuyNode(2);
	BTNode* node3 = BuyNode(3);
	BTNode* node4 = BuyNode(4);


	node1->left = node2;
	node1->right = node3;
	node2->left = node4;
}

回顾二叉树的概念,二叉树分为空树和非空二叉树,非空二叉树由根结点,根结点的左子树,根结点的右子树组成的 根结点的左子树和右子树分别是由子树的结点,子树结点的左子树和子树结点的右子树组成,因此二叉树定义是递归式的,后序链式二叉树的操作中基本都是按照该概念实现的。

2.实现链式二叉树书各个接口

//前序遍历
void PreOrder(BTNode* root);

//中序遍历
void InOrder(BTNode* root);

//后序遍历
void PostOrder(BTNode* root);

// ⼆叉树结点个数
int BinaryTreeSize(BTNode * root);

//二叉树叶子结点个数
int BinaryTreeLevelSize(BTNode* root);

//二叉树第k层结点个数
int BinaryTreeLevelkSize(BTNode* root, BTDataType k);

//二叉树的深度/高度
int BinaryTreeDepth(BTNode* root);

//二叉树查找值为x的结点
BTNode* BinaryTreeFind(BTNode* root, BTDataType x);

//二叉树的销毁
void BinaryTreeDestory(BTNode** root);

//层序遍历
void LevelOrder(BTNode* root);

//判断是否为完全二叉树
bool BinaryTreeComplete(BTNo

2.1前中后序遍历 

二叉树的操作离不开树的遍历,我们先来看看二叉树的遍历有哪些方式: 

 

2.1.1遍历规则

1.前序遍历(Preorder Traversal 亦称先序遍历):访问根结点的操作发生在遍历其左右子树之前。访问顺序为:根结点、左子树、右子树 。

2.中序遍历(Inorder Traversal亦称中序遍历):访问根结点的操作发生在遍历其左右子树之中。访问顺序为:左子树、根结点、右子树。

3.后序遍历(Postorder Traversal):访问根节点的操作发生在遍历其左右子树之后。访问顺序为:左子树、右子树、根结点。

代码实现:

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

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

 

前序遍历结果:1 2 3 4 5 6

中序遍历结果:3 2 1 5 4 6 

 后序遍历结果:3 2 5 6 4 1

2.2结点个数以及高度等

2.2.1二叉树的结点个数

二叉树的结点个数=根结点+左节点个数+右节点个数

// ⼆叉树结点个数
int BinaryTreeSize(BTNode* root)
{
	if (root == NULL)
	{
		return 0;
	}
	return 1 + BinaryTreeSize(root->left) + BinaryTreeSize(root->right);
}

2.2.2二叉树的叶子结点个数

叶子结点就是没有孩子结点的结点。当根结点为空时返回0,当结点的左右孩子结点都为NULL时此节点为叶子结点,因此我们只需要求出左右子树的叶子节点的个数相加就是二叉树的叶子结点个数,代码如下:

//二叉树叶子结点个数
int BinaryTreeLevelSize(BTNode* root)
{
	if (root == NULL)
	{
		return 0;
	}
	if (root->left ==NULL && root->right == NULL)
	{
		return 1;
	}
	return BinaryTreeLevelSize(root->left) + BinaryTreeLevelSize(root->right);
}

2.2.3二叉树第k层结点个数

我们需要一个变量k来说明求的是第几层的结点个数,我们需要采用递归的方式去求每次调用函数的时候都需要k-1,由于根结点就是第一层所以k==1时返回1,根结点为NULL时返回0.

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

 2.2.4二叉树的深度

//二叉树的深度/高度
int BinaryTreeDepth(BTNode* root)
{
	if (root == NULL)
	{
		return 0;
	}
	int leftdeep = BinaryTreeDepth(root->left);
	int rightdeep = BinaryTreeDepth(root->right);

	return leftdeep > rightdeep ? leftdeep + 1 : rightdeep + 1;
}

 2.2.5二叉树查找值为x的结点

根结点为NULL时直接点返回空指针,当结点里面的数据域和x相等时返回该节点,定义两个结构体指针leftfind、rightfind用根的左右子树嵌套调用函数当leftfind 或者rightfind不为空时则找到了返回该指针。

//二叉树查找值为x的结点
BTNode* BinaryTreeFind(BTNode* root, BTDataType x)
{
	if (root == NULL)
	{
		return NULL;
	}
	if (root->data == x)
	{
		return root;
	}
	BTNode* leftfind = BinaryTreeFind(root->left, x);
	if (leftfind)
	{
		return leftfind;
	}
	BTNode* rightfind = BinaryTreeFind(root->right, x);
	if (rightfind)
	{
		return rightfind;
	}
	return NULL;
}

2.2.6二叉树的销毁

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

3.层序遍历

除了先序遍历、中序遍历、后序遍历外,还可以对二叉树进行层序遍历,设二叉树的根结点所在层数为1,层序遍历就是从所在二叉树的根结点出发,首先访问第一层的树根结点,然后从左到右访问第二层上的结点,接着时第三层的结点,以此类推,自上而下,自左至右逐层访问树的结点。

实现层序遍历我们需要额外借助队列这个数据结构。


//层序遍历
void LevelOrder(BTNode* root)
{
	Queue q;
	QueueInit(&q);
	QueuePush(&q, root);
	while (!QueueEmpty(&q))
	{
		//取队头,打印
		BTNode* front = QueueFront(&q);
		printf("%d ", front->data);
		//删除队头
		QueuePop(&q);
		//队头结点的左右孩子结点入队尾
		if (front->left)
		{
			QueuePush(&q, front->left);
		}
		if (front->right)
		{
			QueuePush(&q, front->right);
		}

	}

	//销毁
	QueueDestory(&q);
}

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

如果最后一层的空结点后面全部都是空结点的话就是完全二叉树,如果中间有不是空结点的话就不是完全二叉树。

//判断是否为完全二叉树
bool BinaryTreeComplete(BTNode* root)
{
	Queue q;
	QueueInit(&q);
	//将根入队列
	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* top = QueueFront(&q);
		QueuePop(&q);
		if (top != NULL)
		{
			QueueDestory(&q);
			return false;
		}
		QueueDestory(&q);
		return true;
	}
}

 

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

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

相关文章

Micrometer Tracing和Zipkin实现链路追踪

一、为什么使用链路追踪 在微服务框架中,一个由客户端发起的请求在后端系统中会经过多个不同的的服务节点调用来协同产生最后的请求结果,每一个前段请求都会形成一条复杂的分布式服务调用链路,链路中的任何一环出现高延时或错误都会引起整个…

【经验分享】ShardingSphere+Springboot-03 : COMPLEX_INLINE 复杂行表达式分片算法

文章目录 3.3 复杂分片算法3.3.1 COMPLEX_INLINE 复杂行表达式分片算法 3.3 复杂分片算法 3.3.1 COMPLEX_INLINE 复杂行表达式分片算法 复合分片比较灵活,适合于分片的字段比较多,分片比较复杂的场景,使用这种分片的话必须对自己的业务比较…

深度学习——神经网络(neural network)详解(二). 带手算步骤,步骤清晰0基础可看

深度学习——神经网络(neural network)详解(二). 手算步骤,步骤清晰0基础可看 前文如下:深度学习——神经网络(neural network)详解(一). 带手算步骤&#x…

Java面试篇(JVM相关专题)

文章目录 0. 前言1. 为什么要学 JVM2. 什么是 JVM3. JVM 的好处3.1 一次编写,到处运行3.2 自动内存管理(基于垃圾回收机制) 4. 要学习哪些 JVM 的哪些内容5. JVM 的组成5.1 程序计数器5.2 堆5.3 什么是虚拟机栈常见问题一:垃圾回收…

代码+视频,R语言VRPM绘制多种模型的彩色列线图

列线图,又称诺莫图(Nomogram),它是建立在回归分析的基础上,使用多个临床指标或者生物属性,然后采用带有分数高低的线段,从而达到设置的目的:基于多个变量的值预测一定的临床结局或者…

机器学习入门篇之监督学习(回归篇)——多元线性回归的原理介绍

在机器学习入门之监督学习(分类篇)-CSDN博客,以及初步接触了机器学习,在这片文章中我们继续沿着思维导图学习监督学习的剩下部分,回归。 在监督学习中,回归是一种预测型建模技术,它涉及预测一个…

尚硅谷谷粒商城项目笔记——十、调试前端项目renren-fast-vue【电脑CPU:AMD】

十、调试前端项目renren-fast-vue 如果遇到其他问题发在评论区,我看到后解决 1 先下载安装git git官网下载地址 2 登录gitee搜索人人开源找到renren-fast-vue复制下载链接。【网课视频中也有详细步骤】 3 下载完成后桌面会出现renren-fast-vue的文件夹 4 开始调…

【阿旭机器学习实战】【39】脑肿瘤数据分析与预测案例:数据分析、预处理、模型训练预测、评估

《------往期经典推荐------》 一、【100个深度学习实战项目】【链接】,持续更新~~ 二、机器学习实战专栏【链接】,已更新31期,欢迎关注,持续更新中~~ 三、深度学习【Pytorch】专栏【链接】 四、【Stable Diffusion绘画系列】专…

python如何判断中文是否一致

Python判断两个相等的中文字符串为false,将两个待比较的字符串都把unicode编码设为‘utf-8’也不能解决问题,具体原因如下: 1、首先查看待比较两个字符串的编码格式 ,使用命令: import chardet ...... string_code c…

macos重装系统 启动U盘制作方法 - createinstallmedia 命令使用方法总结

macos重装系统比windows要稍微复杂一些,不过还好,macos系统安装app这个Apple官方提供的系统软件里面默认就内置了一个可用为我们制作启动盘的工具 createinstallmedia 我们下载的apple安装镜像要门是 dmg/pkg/iso 的压缩档案格式的,要么是 x…

智慧安监管理平台建设方案

1. 前言:智慧安监云平台概述 "互联网"安全生产监管监测大数据平台,利用移动互联网、物联网、云计算等技术,实现安全生产监管业务的智能化处理和统一集中管理。平台旨在构建服务导向的智慧安监管理平台,推动安全生产信息…

React 后台管理项目 入门项目 简洁清晰保姆级内容讲解

序章 React Hook的后台管理项目,从0到1搭建,内容非常丰富涵盖项目搭建、路由配置、用户鉴权、首页报表、用户列表、前后端联调等功能,推荐指数:5颗星! 视频学习链接: React 通用后台管理-零基础从0到1详细的入门保姆…

PHYS_OPT_SKIPPED

当跳过候选基元单元的物理优化时 单元格的PHYS_OPT_MODIFIED属性已更新,以反映跳过的优化。 当对同一单元格跳过多个优化时,OPT_skipped值包含 跳过的优化列表。 架构支持 所有架构。 适用对象 PHYS_OPT_SKIPPED属性放置在单元格上。 价值观 下表列出了各…

【Qt】动态加载DLL之QLibrary类学习(内含完整Demo源码)

各位看官这里是目录↓↓↓,点击直达哦~ 前言一、QLibrary简介二、常用方法2.1 构造函数2.2 设置要访问的动态库——setFileName()2.3 加载动态库——load()2.4 获取动态库的名字——fileName()2.5 解析共享库中的符号——resolve() 三、示例(Demo&#x…

入门学习使用overleaf和latex

文章目录 1.下载对应的latex论文模板2.overleaf平台的使用2.1overleaf平台的介绍2.2overleaf平台模板文件的上传2.3latex语法的学习2.3.2 分段(如下图显示)2.3.3 其他2.3.4简单latex实操2.3.5 换行符和换页符2.3.6左右居中对齐2.3.7 字体设置2.3.8插入固定位置图片2.3.9文字包围…

KillWxapkg 自动化反编译微信小程序,小程序安全评估工具,发现小程序安全问题,自动解密,解包,可还原工程目录,支持修改Hook,小程序

纯Golang实现,一个用于自动化反编译微信小程序的工具,小程序安全利器,自动解密,解包,可还原工程目录,支持微信开发者工具运行 由于采用了UPX压缩的软件体积,工具运行时可能会出现错误报告&…

Springboot整合Flowable入门-学习笔记

目录 1、定义流程(画图) 2、Springboot部署流程 3、Springboot删除所有流程 4、Springboot根据 流程部署ID 查询 流程定义ID 5、Springboot启动(发起)流程 6、Springboot查询任务 6.1全部任务 6.2我的任务(代办任务) 7、…

Ubuntu怎么进入救援模式或单用户模式

进入救援模式(Rescue Mode)或单用户模式(Single User Mode)的方法取决于你所使用的Linux发行版。以下是通用的步骤,适用于大多数基于GRUB引导的系统,如Ubuntu、Debian、CentOS等: 重启你的系统。…

【Python第三方库】Requests全面解析

文章目录 安装基本用法测试网站发送GET请求发送POST请求更多请求请求参数请求头其他常用请求属性处理响应响应状态码响应内容 处理超时处理异常 requests 是一个非常流行的 Python HTTP 库,用于发送所有类型的 HTTP 请求。它简洁易用,能够处理复杂的请求…

DAMA学习笔记(十三)-大数据和数据科学

1.引言 大数据不仅指数据的量大,也指数据的种类多(结构化的和非结构化的,文档、文件、音频、视频、流数据等),以及数据产生的速度快。数据科学家是指从从数据中探究、研发预测模型、机器学习模型、规范性模型和分析方法…