二叉树《数据结构》

news2024/9/23 19:14:24

二叉树

  • 1. 树概念及结构
    • 1.1 树的概念
    • 1.2树的概念
    • 1.3 树的表示
  • 2. 二叉树概念及结构
    • 2.1 二叉树概念
    • 2.4 二叉树的性质
    • 练习
  • 3. 二叉树顺序结构及实现
    • 3.1 二叉树的顺序结构
    • 3.2堆的结构及概念
    • 练习
    • 3.3堆的实现
      • 3.3.1堆的向下调整算法
      • 3.3.2堆的创建
      • 3.3.3 堆的插入
      • 3.3.4 堆的删除
      • 3.3.5堆的代码实现

1. 树概念及结构

1.1 树的概念

树是一种非线性的数据结构,它是由n(n>=0)个有限结点组成一个具有层次关系的集合。把它叫做树是因
为它看起来像一棵倒挂的树,也就是说它是根朝上,而叶朝下的。

  1. 有一个特殊的结点,称为根结点,根结点没有前驱结点
  2. 除根结点外,其余结点被分成M(M>0)个互不相交的集合T1、T2、……、Tm,其中每一个集合Ti(1<= i
    <= m)又是一棵结构与树类似的子树。每棵子树的根结点有且只有一个前驱,因此,树是递归定义的。

    在这里插入图片描述
    在这里插入图片描述
    有一点需要注意:树形结构中,子树之间不能有交集,否则就不是树形结构。

1.2树的概念

在这里插入图片描述

结点的度:一个结点含有的子树的个数称为该结点的度;如上图:A的为6

叶结点或终端结点:度为0的结点称为叶结点;如上图:B、C、H、I…等结点为叶结点

非终端结点或分支结点:度不为0的结点;如上图:D、E、F、G…等结点为分支结点

双亲结点或父结点:若一个结点含有子结点,则这个结点称为其子结点的父结点;如上图:A是B的父结点

孩子结点或子结点:一个结点含有的子树的根结点称为该结点的子结点;如上图:B是A的孩子结点

兄弟结点:具有相同父结点的结点互称为兄弟结点;如上图:B、C是兄弟结点

树的度:一棵树中,最大的结点的度称为树的度;如上图:树的度为6

结点的层次:从根开始定义起,根为第1层,根的子结点为第2层,以此类推;

树的高度或深度:树中结点的最大层次;如上图:树的高度为4

堂兄弟结点:双亲在同一层的结点互为堂兄弟;如上图:H、I互为兄弟结点

结点的祖先:从根到该结点所经分支上的所有结点;如上图:A是所有结点的祖先

子孙:以某结点为根的子树中任一结点都称为该结点的子孙。如上图:所有结点都是A的子孙

森林:由m(m>0)棵互不相交的树的集合称为森林;

1.3 树的表示

孩子兄弟表达法:

typedef int type
struct Node
{
struct Node*firstChild;//第一个孩子节点
struct Node*NextBrother;//指向其下一个兄弟节点
type data;//数据
}

在这里插入图片描述

2. 二叉树概念及结构

2.1 二叉树概念

1.由一个根节点加上两颗子树称为左子树和右子树构成了二叉树
2. 二叉树不存在度大于2的结点
3.二叉树的子树有左右之分,次序不能颠倒,因此二叉树是有序的

在这里插入图片描述
2.2特殊的二叉树:
1.满二叉树:一个二叉树,如果每一个层的结点数都达到最大值,则这个二叉树就是满二叉树。也就是说,如果一个二叉树的层数为K,且结点总数是2^k-1,则它就是满二叉树。
2.完全二叉树:完全二叉树是效率很高的数据结构,完全二叉树是由满二叉树而引出来的。对于深度为K
的,有n个结点的二叉树,当且仅当其每一个结点都与深度为K的满二叉树中编号从1至n的结点一一对
应时称之为完全二叉树。 要注意的是满二叉树是一种特殊的完全二叉树。
在这里插入图片描述

2.4 二叉树的性质

  1. 若规定根结点的层数为1,则一棵非空二叉树的第i层上最多有2^(i-1) 个结点.
  2. 若规定根结点的层数为1,则深度为h的二叉树的最大结点数是2^h-1 .
  3. 对任何一棵二叉树, 如果度为0其叶结点个数为n1 , 度为2的分支结点个数为 n2,则有 n1= n2+1

假设二叉树有N个结点:
从总结点数角度考虑:N = n0 + n1 + n2 ①//n1为度为1的节点
从边的角度考虑,N个结点的任意二叉树,总共有N-1条边
因为二叉树中每个结点都有双亲,根结点没有双亲,每个节点向上与其双亲之间存在一条边
因此N个结点的二叉树总共有N-1条边
因为度为0的结点没有孩子,故度为0的结点不产生边; 度为1的结点只有一个孩子,故每个度为1的结
点* * 产生一条边; 度为2的结点有2个孩子,故每个度为2的结点产生两条边,所以总边数为:
n1+2n2 故从边的角度考虑:N-1 = n1 + 2n2 ② 结合① 和 ②得:n0 + n1 + n2 = n1 + 2n2 - 1 即:n0 = n2 + 1

  1. 若规定根结点的层数为1,具有n个结点的满二叉树的深度,h=log2(n+1),{log2(n+1)是以2为底,n+1为对数}
  2. 对于具有n个结点的完全二叉树,如果按照从上至下从左至右的数组顺序对所有结点从0开始编号,则对
    于序号为i的结点有:
    若i>0,i位置结点的双亲序号:(i-1)/2;i=0,i为根结点编号,无双亲结点
    若2i+1<n,左孩子序号:2i+1,2i+1>=n否则无左孩子
    若2i+2<n,右孩子序号:2i+2,2i+2>=n否则无右孩子

练习

1.某二叉树共有 399 个结点,其中有 199 个度为 2 的结点,则该二叉树中的叶子结点数为( )
A 不存在这样的二叉树
B 200
C 198
D 199

根据性质3可以得出n1=n2+1,答案为:B

2.下列数据结构中,不适合采用顺序存储结构的是( )
A 非完全二叉树
B 堆
C 队列
D 栈

堆的底层是数组,栈底层是数组,队列也可以用数组来实现,而非完全二叉树不适用,满二叉树和完全二叉树可以按顺序储存 ,答案为:A

3.在具有 2n 个结点的完全二叉树中,叶子结点个数为( )
A n
B n+1
C n-1
D n/2

可以根据公式进行推导,假设n0是度为0的结点总数(即叶子结点数),n1是度为1的结点总数,n2是度为2的结点总数,则 :
①n= n0+n1+n2(其中n为完全二叉树的结点总数);又因为一个度为2的结点会有2个子结点,一个度为1的结点会有1个子结点,除根结点外其他结点都有父结点,

②n= 1+n1+2n2;由①、②两式把n2消去得:n= 2n0+n1-1,由于完全二叉树中度为1的结点数只有两种可能0或1,由此得到n0=n/2 或 n0=(n+1)/2。

简便来算,就是 n0=n/2,其中n为奇数时(n1=0)向上取整;n为偶数时(n1=1)。可根据完全二叉树的结点总数计算出叶子结点数。所以答案为:A

4.一棵完全二叉树的结点数位为531个,那么这棵树的高度为( )
A 11
B 10
C 8
D 12

根据性质4得出:答案为B

5.一个具有767个结点的完全二叉树,其叶子结点个数为()
A 383
B 384
C 385
D 386

简便来算,就是 n0=n/2,其中n为奇数时(n1=0)向上取整;n为偶数时(n1=1)。可根据完全二叉树的结点总数计算出叶子结点数。所以答案为:B

3. 二叉树顺序结构及实现

3.1 二叉树的顺序结构

  1. 顺序存储
    顺序结构存储就是使用数组来存储,一般使用数组只适合表示完全二叉树,因为不是完全二叉树会有空间的浪费。而现实中使用中只有堆才会使用数组来存储,关于堆我们后面的章节会专门讲解。二叉树顺序存储在物理上是一个数组,在逻辑上是一颗二叉树。
    在这里插入图片描述

3.2堆的结构及概念

堆的性质:

堆中某个结点的值总是不大于或不小于其父结点的值;
堆总是一棵完全二叉树。
在这里插入图片描述

练习

1.下列关键字序列为堆的是:()
A100,60,70,50,32,65
B 60,70,65,50,32,100
C 65,100,70,32,50,60
D 70,65,100,32,50,60
E 32,50,100,70,65,60
F 50,100,70,65,60,32

答案为:A

2.已知小根堆为8,15,10,21,34,16,12,删除关键字8之后需重建堆,在此过程中,关键字之间的比较次数是()。
A 1
B 2
C 3
D 4

8与12交换位置后,12与15比较,在与10比较,交换10与12,最后12在与16比较
一共比较了3次
答案为C

3.3堆的实现

3.3.1堆的向下调整算法

现在我们给出一个数组,逻辑上看做一颗完全二叉树。我们通过从根结点开始的向下调整算法可以把它调整成一个小堆。向下调整算法有一个前提:左右子树必须是一个堆,才能调整。

int array[] = {27,15,19,18,28,34,65,49,25,37};

在这里插入图片描述

3.3.2堆的创建

下面我们给出一个数组,这个数组逻辑上可以看做一颗完全二叉树,但是还不是一个堆,现在我们通过算法,把它构建成一个堆。根结点左右子树不是堆,我们怎么调整呢?这里我们从倒数的第一个非叶子结点的子树开始调整,一直调整到根结点的树,就可以调整成堆。

inta[] = {1,5,3,8,7,6};

在这里插入图片描述

3.3.3 堆的插入

先插入一个10到数组的尾上,再进行向上调整算法,直到满足堆
在这里插入图片描述

3.3.4 堆的删除

删除堆是删除堆顶的数据,将堆顶的数据根最后一个数据一换,然后删除数组最后一个数据,再进行向下调整算法。

在这里插入图片描述

3.3.5堆的代码实现

typedef int HPDataType;

typedef struct Heap
{
	HPDataType* a;
	int size;
	int capacity;
}HP;

void Swap(HPDataType* p1, HPDataType* p2);
void AdjustUp(HPDataType* a, int child);
void AdjustDown(HPDataType* a, int n, int parent);

void HPInit(HP* php);
void HPDestroy(HP* php);
void HPPush(HP* php, HPDataType x);
void HPPop(HP* php);
HPDataType HPTop(HP* php);
bool HPEmpty(HP* php);

//堆接口实现
void HPInit(HP* php)
{
	assert(php);
	php->a = NULL;
	php->size = php->capacity = 0;
}

void HPDestroy(HP* php)
{
	assert(php);
	free(php->a);
	php->a = NULL;
	php->size = php->capacity = 0;
}

void Swap(HPDataType* p1, HPDataType* p2)
{
	HPDataType tmp = *p1;
	*p1 = *p2;
	*p2 = tmp;
}

void AdjustUp(HPDataType* a, int child)
{
	// 初始条件
	// 中间过程
	// 结束条件
	int parent = (child - 1) / 2;
	//while (parent >= 0)
	while (child > 0)
	{
		if (a[child] > a[parent])
		{
			Swap(&a[child], &a[parent]);
			child = parent;
			parent = (child - 1) / 2;
		}
		else
		{
			break;
		}
	}
}

void HPPush(HP* php, HPDataType x)
{
	assert(php);

	if (php->size == php->capacity)
	{
		int newcapacity = php->capacity == 0 ? 4 : php->capacity * 2;
		HPDataType* tmp = (HPDataType*)realloc(php->a, newcapacity * sizeof(HPDataType));
		if (tmp == NULL)
		{
			perror("realloc fail");
			return;
		}

		php->a = tmp;
		php->capacity = newcapacity;
	}

	php->a[php->size] = x;
	php->size++;

	AdjustUp(php->a, php->size - 1);
}

void AdjustDown(HPDataType* a, int n, int parent)
{
	// 先假设左孩子小
	int child = parent * 2 + 1;

	while (child < n)  // child >= n说明孩子不存在,调整到叶子了
	{
		// 找出小的那个孩子
		if (child + 1 < n && a[child + 1] > a[child])
		{
			++child;
		}

		if (a[child] > a[parent])
		{
			Swap(&a[child], &a[parent]);
			parent = child;
			child = parent * 2 + 1;
		}
		else
		{
			break;
		}
	}
}

// logN
void HPPop(HP* php)
{
	assert(php);
	assert(php->size > 0);
	Swap(&php->a[0], &php->a[php->size - 1]);
	php->size--;

	AdjustDown(php->a, php->size, 0);
}

HPDataType HPTop(HP* php)
{
	assert(php);
	assert(php->size > 0);

	return php->a[0];
}

bool HPEmpty(HP* php)
{
	assert(php);

	return php->size == 0;
}

谢谢观看!!!

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

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

相关文章

C2M商业模式分析与运营平台建设解决方案(五)

C2M商业模式通过直接对接消费者需求与制造商&#xff0c;实现了生产与市场需求的精准匹配&#xff0c;本文提出的解决方案重点在于构建一个智能化运营平台&#xff0c;通过集成先进的大数据分析、人工智能技术和灵活的供应链管理系统&#xff0c;全面提升需求预测的准确性、生产…

【若依框架】代码生成详细教程,15分钟搭建Springboot+Vue3前后端分离项目,基于Mysql8数据库和Redis5,管理后台前端基于Vue3和Element Plus,开发小程序数据后台

今天我们来借助若依来快速的搭建一个基于springboot的Java管理后台&#xff0c;后台网页使用vue3和 Element Plus来快速搭建。这里我们可以借助若依自动生成Java和vue3代码&#xff0c;这就是若依的强大之处&#xff0c;即便你不会Java和vue开发&#xff0c;只要跟着石头哥也可…

loadlibrary failed with error 126:找不到指定模块

买了一张w4300回来装到nas上&#xff0c;核显HD630输出的 打开cad的时候发现图形显卡是hd630&#xff0c;w4300一直没有被驱动&#xff0c;于是去设置里面将cad强行用高性能打开 结果一直报错&#xff1a;loadlibrary failed with error 126:找不到指定模块 网上搜索了半天&am…

招生简章不会设计?这个网站可以供你参考

招生简章是学校与潜在学生之间的第一座桥梁&#xff0c;它的设计直接影响到学校的形象和招生效果。如果你在设计招生简章时感到困惑&#xff0c;不妨参考以下几个要点&#xff0c;让你的招生简章更加吸引人。 1.明确目标受众&#xff1a;在设计招生简章之前&#xff0c;首先要明…

项目实战:Qt+Opencv相机标定工具v1.3.0(支持打开摄像头、视频文件和网络地址,支持标定过程查看、删除和动态评价误差率,支持追加标定等等)

若该文为原创文章&#xff0c;转载请注明出处 本文章博客地址&#xff1a;https://hpzwl.blog.csdn.net/article/details/141334834 长沙红胖子Qt&#xff08;长沙创微智科&#xff09;博文大全&#xff1a;开发技术集合&#xff08;包含Qt实用技术、树莓派、三维、OpenCV、Op…

运维小技能:通过调整JVM的默认内存配置来解决内存溢出(‌OutOfMemoryError)‌或栈溢出(‌StackOverflowError)‌等错误

文章目录 引言I 调整JVM的默认堆内存配置1.1 java命令启动jar包时配置JVM 的内存参数1.2 基于Tomcat服务器部署的java应用,配置JVM 的内存参数II 案例: Linux 操作系统设置tomcat的 JVM 的内存参数查找Tomcat位置: 快速定位服务状态和部署位置具体配置步骤扩展: 监测Nginx访…

配置stm32cubemx采集stm32H743IIT6,通过DMA实现多通道和多模块ADC的采集,亲测有效!

之前写到stm32cubemx通过阻塞实现单通道和多通道的ADC的采集。 本文分享通过DMA实现单模块多通道和多模块多通道的ADC采集。 stm32cubemx的版本6.10.0。 一、DMA采集多通道ADC数据 阻塞采集是每次采集adc数据&#xff0c;cpu死等&#xff0c;直到采集完或者在设定时间超时没…

不能使用乘除法、for、while、if、else、switch、case求1+2+3+...+n

求123...n_牛客题霸_牛客网 (nowcoder.com) 描述 求123...n&#xff0c;要求不能使用乘除法、for、while、if、else、switch、case等关键字及条件判断语句&#xff08;A?B:C&#xff09;。 数据范围&#xff1a; 0<n≤2000<n≤200 进阶&#xff1a; 空间复杂度 O(1)O(…

PCRNet: Point Cloud Registration Network using PointNet Encoding 论文解读

目录 一、导言 二、先导知识 1、Frobenius范数 三、相关工作 1、点云配准工作 2、PointNet 3、基于深度学习的点云配准 四、PCRNet 1、PCRNet 2、Iterative PCRNet 3、损失函数 五、实验 一、导言 本论文收录于CVPR2019&#xff0c;本论文提出了一种依赖PointNet网…

快排补充(挖坑法,lomuto前后指针,非递归法)

挖坑法 挖坑法动态示意图 挖坑法方法分析 创建左右指针。⾸先从右向左找出⽐基准⼩的数据&#xff0c;找到后⽴即放⼊左边坑中&#xff0c;当前位置变为新 的"坑"&#xff0c;然后从左向右找出⽐基准⼤的数据&#xff0c;找到后⽴即放⼊右边坑中&#xff0c;当前位置…

STM32——CAN通讯基础知识

CAN 协议简介 CAN 是控制器局域网络 (Controller Area Network) 的简称&#xff0c;它是由研发和生产汽车电子产品著称的德国 BOSCH 公司开发的&#xff0c;并最终成为国际标准(ISO11519以及ISO11898),是国际上应用最广泛的现场总线之一。差异点如下&#xff1a; 高速CAN可以达…

关于shortlink项目重构增加了del_time字段自己出现的问题

最近刚做完shortlink项目的重构问题,其中增加del_time作为t_link表的唯一索引要注意几点问题. 1.数据库表中的del_time字段类型为什么,一定要和DO中的类型统一. 2.del_time作为唯一索引不要写死了,不然就无法创建短连接了,这里我是将del_time修改成date类型,然后通过new date…

Python数分实战

学习视频&#xff1a;【课程3.0】Python基础与分析实战_哔哩哔哩_bilibili 由于学习过python进行数据分析&#xff0c;所以就简单记录一下&#xff0c;最主要学习的还是视频最后的两个项目&#xff0c;进行实战 之前想不明白明明有很智能的软件做数据分析&#xff0c;为什么还要…

XXX【5】观察者模式

文件分割案例&#xff1a; 用户输入文件路径filePath和分割数量number&#xff0c;初始化出一个FileSplitter实例对象&#xff0c;然后调用split方法文件分割。 假如&#xff1a;我要加一个进度条的设计 抽象不能依赖于实现细节&#xff1a;在第6行的m_progressBar是一个进度通…

【深度解析】WRF-LES与PALM微尺度气象大涡模拟

查看原文>>>【深度解析】WRF-LES与PALM微尺度气象大涡模拟 针对微尺度气象的复杂性&#xff0c;大涡模拟&#xff08;LES&#xff09;提供了一种无可比拟的解决方案。微尺度气象学涉及对小范围内的大气过程进行精确模拟&#xff0c;这些过程往往与天气模式、地形影响和…

vimplus出现的错误,如何解决??

&#x1f3c6;本文收录于《CSDN问答解惑-专业版》专栏&#xff0c;主要记录项目实战过程中的Bug之前因后果及提供真实有效的解决方案&#xff0c;希望能够助你一臂之力&#xff0c;帮你早日登顶实现财富自由&#x1f680;&#xff1b;同时&#xff0c;欢迎大家关注&&收…

C++面向对象编程(上)

类与对象属于面向对象的程序设计思想(Object Oriented Programming)&#xff0c;简称OOP。 面向对象基础理论 面向对象是一种对现实世界理解和抽象的方法&#xff0c;是计算机编程技术发展到一定阶段后的产物&#xff0c;是一种软件开发的方法 面向对象四大特性 1.抽象 忽…

数据库(五):多表设计和多表查询

项目开发中&#xff0c;在进行数据库表结构设计时&#xff0c;会根据业务需求及业务模块之间的关系&#xff0c;分析并设计表结构&#xff0c;由于业务之间相互关联&#xff0c;所以各个表结构之间也存在各种联系&#xff0c;基本上分为三种&#xff1a;一对一、多对一、一对多…

如何在寂静中用电脑找回失踪的手机?远程控制了解一下

经过一番努力&#xff0c;我终于成功地将孩子哄睡了。夜深人静&#xff0c;好不容易有了一点自己的时间&#xff0c;就想刷手机放松放松&#xff0c;顺便看看有没有重要信息。但刚才专心哄孩子去了&#xff0c;一时就忘记哄孩子之前&#xff0c;顺手把手机放哪里去了。 但找过手…

进程相关知识

进程和程序的区别 程序 程序是静态的&#xff0c;是存储在硬盘、SSD等存储介质中的一个文件&#xff0c;通常由源代码&#xff08;如 .c 文件&#xff09;编译生成的二进制可执行文件&#xff08;如 a.out&#xff09;。程序包含了指令和数据&#xff0c;但在未被执行时&#…