【数据结构】树以及堆的讲解

news2024/10/6 6:45:40

(这里写自定义目录标题)

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录

  • 前言
  • 一、树的概念?
  • 二、树的表示方法
  • 三、树的实际应用
  • 四、二叉树概念以及结构
    • 1.概念
    • 2.特殊的二叉树
    • 3.二叉树的性质
    • 4.二叉树的存储结构
    • 5.引入堆的概念以及结构
    • 6.堆的实现以及堆排序
    • 7.时间复杂度问题
    • 8.TPopk问题
  • 总结


前言

树形结构是一种非线性的数据结构,其应用非常广泛,由树形结构可以引申出二叉树、堆等等的特殊树。
学习树对我们今后的工作帮助非常大。

一、树的概念?

树是一种非线性的数据结构,它是n(n>=0)个有限结点组成的一个具有层次关系的集合。把它叫做树是因为它看起来像一棵倒挂的树,也就是说它根朝上,而叶朝下。简单来讲就是–>树+人类亲缘关系描述
在这里插入图片描述

**- 根结点:没有父结点,且为所有结点的祖先的结点,如上图的A

  • 节点的度:一个节点含有的子树个数称为该节点的度,如上图:A-6、D-1、E-2
  • 叶子节点:度为0的结点,如上图的B、C
  • 分支节点:度不为0的结点,如上图的D、E、F
  • 父节点:一个节点含有子节点的节点,称为父节点,如:A为B、C、D、E的父节点
  • 子节点:一个节点有父节点的节点称为子节点,如:B、C、D、E为A的子节点
  • 兄弟节点:具有相同父节点的节点,如:I、J的父节点都为E,则I和J为兄弟节点
  • 树的度:一棵树中,最大的节点度,如上图:树的度为6
  • 节点的层次:从根节点开始算,根为1,依次往下计算
  • 树的高度或深度:树的节点最大层,如上图:4
  • 堂兄弟:处于同一层,但又不是兄弟节点的节点
  • 节点的祖先:从根节点到所经分支上的所有节点
  • 子孙:以某节点为根的子树中任一节点都称为该节点的子孙,如:所有节点都是A的子孙
  • 森林:由多棵不相交的数组成**

二、树的表示方法

树的存储表示既要保存值域,也要保存节点和节点之间的关系,实际中树的表示方法有很多种,如:双亲表示法、孩子表示法等等,但我们最常用的还是孩子兄弟表示法。
在这里插入图片描述
在这里插入图片描述

三、树的实际应用

在这里插入图片描述
在实际应用中,树结构常常用于制作文件目录

四、二叉树概念以及结构

1.概念

一棵二叉树是结点的一个有限集合,构成二叉树有规定:
1.一定是由一个根节点加上两棵左子树和右子树组成
2.二叉树不存在大于2的节点
3.二叉树的子树有左右之分,次序不能颠倒,因此二叉树是有序树

2.特殊的二叉树

  1. 满二叉树
    在这里插入图片描述
    每一层的节点数都达到最大值,则称这个二叉树为满二叉树,就是说,如果一个二叉树层数为h,且节点总数为2^h-1,则为满二叉树
    在这里插入图片描述
    2.完全二叉树
    在这里插入图片描述
    完全二叉树为(最后一层-1)层必须为满节点,最后一层可以没有分支节点,若有,则需要有序。
    注意:满二叉树是一种特殊的完全二叉树
    在这里插入图片描述

3.二叉树的性质

3.1 如何计算高度为h的节点个数?
在这里插入图片描述
3.2 如何计算二叉树的高度(h)
已知节点个数,求高度(h)
N为节点个数
公式:(2^h)-1 = N ⇒ F(h) = log N+1;

4.二叉树的存储结构

  1. 顺序存储
    顺序结构存储就是用数组进行存储,但一般用数组进行存储只用来存储完全二叉树,因为不是完全二叉树会有空间浪费,起原因是完全二叉树的子树必须是一个接着一个的,而其它形式的没这种规定
    在这里插入图片描述
    父子间下标关系:
    在这里插入图片描述

5.引入堆的概念以及结构

1.二叉树的顺序结构
普通的二叉树是不适合用数组来存储的,因为会浪费大量的空间,而往往在现实中,我们会把堆(一种二叉树)使用顺序结构的数组进行存储。
2.堆
2.1、是一种完全二叉树。
2.2、大堆:树中任何一个父亲都大于或等于孩子
在这里插入图片描述
小堆:树中任何一个父亲都小于或等于孩子
在这里插入图片描述

6.堆的实现以及堆排序

核心算法:

6.1 向上调整算法
前提:是一个堆
在这里插入图片描述

6.2 向下调整算法
前提:左右子树是一个堆
在这里插入图片描述

7.时间复杂度问题

向上调整建堆:
在这里插入图片描述
向下调整建堆
在这里插入图片描述
堆排序
在这里插入图片描述

8.TPopk问题

什么是TPopk问题?
TPopk问题是堆的应用之一,其是要实现N个数中找出最大/最小数的前K个.

实现方法:
1.用于简单场景,如N的值不大的情况
在这里插入图片描述

//找出前k个最大的数
void Swap(int* father, int* child)
{
	int tmp = *father;
	*father = *child;
	*child = tmp;
}
void AdjustDown(int* tpopk, int n,int father)
{
	int child = (father * 2) + 1;
	while (child<n)
	{
		if (child+1<n && tpopk[child]<tpopk[child+1])
		{
			child++;
		}
		if (tpopk[father] < tpopk[child])
		{
			Swap(&tpopk[father], &tpopk[child]);//交换
			father = child;
			child = (father * 2) + 1;
		}
		else
		{
			break;
		}
	}
}
void Adjustcreate(int* tpopk,int n)
{
	for (int i = (n-1-1)/2; i >=0; i--)
	{
		AdjustDown(tpopk,n,i);
	}
}
void AdjustPop(int* tpopk,int n)
{
	//交换首尾元素
	Swap(&(tpopk[0]), &(tpopk[n - 1]));
	n--;
	AdjustDown(tpopk, n, 0);
}
void TPopk(int* tpopk, int n)
{
	//1.建堆
	//采用向下调整建堆
	Adjustcreate(tpopk,n);

	//2.Tpop数据后,Pop数据
	printf("%d ", tpopk[0]);
	for (int i = 0; i < 4; i++)
	{
		AdjustPop(tpopk, n--);
		printf("%d ", tpopk[0]);
	}
}
int main()
{
	int tpopk[] = {5,2,9,6,1,4,10,50};
	int size = sizeof(tpopk) / sizeof(int);
	TPopk(tpopk,size);
	return 0;
}

2.用于复杂场景,如N的值太大的情况

#include<stdio.h>
#include<stdlib.h>
#include<time.h>
void Swap(int* child,int* father)
{
	int tmp = *child;
	*child = *father;
	*father = tmp;
}
void AdjustDown(int* a,int k,int father)
{
	int child = (father * 2) + 1;
	while (child<k)
	{
		if (child+1<k && a[child] >a[child+1])
		{
			child++;
		}
		if (a[child]<a[father])
		{
			Swap(&a[child],&a[father]);
			father = child;
			child = (father * 2) + 1;
		}
		else
		{
			break;
		}
	}
}
void AdjustDownC(int* a,int k)
{
	for (int i = (k-1-1)/2; i >=0; i--)
	{
		AdjustDown(a,k,i);
	}
}
void PrintTopK(int* a,int n,int k)
{
	//1.将前K个数建堆
	AdjustDownC(a,k);

	//2.将N-K的数,依次与堆顶元素比较
	for (int i = k; i < n; i++)
	{
		if (a[0] < a[i])
		{
			Swap(&a[0],&a[i]);
			AdjustDown(a,k,0);
		}
	}
	
}
void Topk()
{
	int n = 10000;
	int* a = (int*)malloc(sizeof(int) * n);
	if (a == NULL)
	{
		perror("malloc fail:");
		return;
	}
	srand((unsigned int)time(0));
	for (int i = 0; i < n; ++i)
	{
		a[i] = rand() % 100;
	}
	a[5] = 1000000 + 1;
	a[1231] = 1000000 + 2;
	a[531] = 1000000 + 3;
	a[5121] = 1000000 + 4;
	a[115] = 1000000 + 5;
	a[2335] = 1000000 + 6;
	a[9999] = 1000000 + 7;
	a[76] = 1000000 + 8;
	a[423] = 1000000 + 9;
	a[3144] = 1000000 + 10;
	PrintTopK(a, n, 10);
	for (int i = 0; i < 10; i++)
	{
		printf("%d ", a[i]);
	}

}
int main()
{
	Topk();
	return 0;
}

总结

这就是我对堆的应用与理解,谢谢观看!

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

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

相关文章

指针与数组--动态数组(2)[1、长度可变的一维动态数组 2、长度可变的二维动态数组]

目录 一、长度可变的一维动态数组 二、长度可变的二维动态数组 由上篇文章的理论&#xff0c;接下来使用例题来阐述。 一、长度可变的一维动态数组 例题1、编程输入某班学生的某门课成绩&#xff0c;计算并输出平均值。学生人数由键盘输入。 #include <stdio.h> #i…

Apache服务器

文章目录 Apache服务器Linux安装ApacheApache文件结构Apache主配置文件案例 配置一台Web服务器 启动用户的个人网站虚拟主机的设定基于IP的虚拟主机基于域名的虚拟主机基于端口的虚拟主机 rewrite重写rewrite使用详解使用案例 域名跳转单个域名跳转多个域名跳转 status状态页ap…

“插入排序:小数据量排序的王者“

文章目录 &#x1f50d;什么是插入排序&#xff1f;&#x1f511;插入排序的优缺点&#x1f680;实现插入排序 &#x1f50d;什么是插入排序&#xff1f; 插入排序是一种简单的排序算法&#xff0c;它的基本思想是&#xff1a;将待排序的元素&#xff0c;从第二个元素开始&…

阿里架构师整理的Java经典面试题1220道(附答案)

学习如逆水行舟&#xff0c;尤其是 IT 行业有着日新月异的节奏&#xff0c;我们更要抓紧每一次可以学习和进步的机会。所以&#xff0c;没有撤退可言 即使是面试跳槽&#xff0c;那也是一个学习的过程。只有全面的复习&#xff0c;才能让我们更好的充实自己&#xff0c;武装自…

内网隧道代理技术(五)之 Netcat反弹Shell

Netcat反弹Shell Netcat简称NC,是一个简单、可靠的网络工具,被誉为网络界的瑞士军刀。通NC可以进行端口扫描、反弹Shell、端口监听和文件传输等操作,常用参数如下&#xff1a; 参数作用-c指定连接后要执行的shell命令-e指定连接后要执行的文件名-k配置 Socket一直存活(若不想…

一文了解远程桌面连接

一文了解远程桌面连接 一、引言1.1、远程桌面连接的概述1.2、远程桌面连接的应用场景 二、远程桌面连接的基本原理2.1、远程桌面连接的工作方式2.2、远程桌面连接的安全性 三、远程桌面连接的实现方法3.1、Windows自带的远程桌面连接3.2、第三方远程桌面连接工具 四、远程桌面连…

一阶低通滤波器(CODESYS FC和FB应用介绍)

一阶RC低通滤波器详细算法介绍请参看下面文章链接: PLC信号处理系列之一阶低通(RC)滤波器算法_plc计算滤波频率_RXXW_Dor的博客-CSDN博客1、先看看RC滤波的优缺点 优点:采用数字滤波算法来实现动态的RC滤波,则能很好的克服模拟滤波器的缺点; 1、在模拟常数要求较大的场合这…

数据挖掘——甘肃省县(区)域农业综合实力研究(论文)

《数据挖掘与分析》课程论文 题目&#xff1a;甘肃省县&#xff08;区&#xff09;域农业综合实力研究 xx学院xx专业xx班&#xff1a;xx 2023年6月 甘肃省县&#xff08;区&#xff09;域农业综合实力研究 xx (xx学院 xx学院) 摘要&#xff1a;本文主要研究甘肃省各县&#…

C语言数组指针和指针数组

文章目录 1 数组指针和指针数组的区别2 数组首地址和数组首元素地址的区别参考 1 数组指针和指针数组的区别 对指针数组和数组指针的概念&#xff0c;相信很多C程序员都会混淆。下面通过两个简单的语句来分析一下二者之间的区别&#xff0c;示例代码如下所示&#xff1a; int…

C/C++的发展历程和未来趋势

文章目录 C/C的起源C/C的应用C/C开发的工具C/C未来趋势 C/C的起源 C语言 C语言是一种通用的高级编程语言&#xff0c;由美国计算机科学家Dennis Ritchie在20世纪70年代初期开发出来。起初&#xff0c;C语言是作为操作系统UNIX的开发语言而创建的。C语言的设计目标是提供一种功…

虚拟文件系统的数据结构

文章目录 虚拟文件系统的数据结构超级快挂载描述符文件系统类型索引节点目录项文件的打开实例和打开文件表 虚拟文件系统的数据结构 虽然不同文件系统类型的物理结构不同&#xff0c;但是虚拟文件系统定义了一套统一的数据结构。 &#xff08;1&#xff09;超级块。文件系统的…

【网络2】MII MDC/MDIO

文章目录 1.MII&#xff1a;ISO网络模型中物理层&#xff08;phy&#xff09;和数据链路层&#xff08;mac&#xff09;属于硬件&#xff0c;其余都属于软件kernel2.MDC/MDIO&#xff1a;不仅管phy&#xff0c;只要支持mdio协议都可以管2.1 BMC速率适配&#xff1a;phy和switch…

二层MAC地址介绍

目录 MAC地址介绍 MAC地址的组成 MAC地址分类 MAC地址的作用 二层交换机介绍 MAC地址表的定义 MAC地址表项类型 二层交换机对数据帧的处理动作 MAC地址介绍 MAC地址&#xff08;Media Access Control Address)&#xff0c;直译为媒体存取控制位地址 MAC地址的组成 MA…

【四、基本shell命令】

1 帮助命令 man 获取帮助信息 [root@redis100 a]# man lshelp 获得shell内置命令的帮助信息 [root@redis100 a]# help cd常用快捷键 2 文件目录类 pwd 显示当前工作目录的绝对路径 pwd:print working directory [root@redis100 ~]# pwd /rootls 列出目录的内容 ls: list…

Hyper-V虚拟机安装和使用

目录 什么是虚拟化技术虚拟化技术有以下几个关键概念&#xff1a;虚拟化技术的优点&#xff1a; 什么是Hyper-V虚拟机Hyper-V虚拟机的关键特点和优势&#xff1a;使用Hyper-V虚拟机我们能做什么 安装Hyper-V系统要求启用Hyper-V功能创建虚拟机安装操作系统 最近在研究人工智能A…

仙境传说RO:NPC对话| mes/next/close函数用法详解

仙境传说RO:NPC对话| mes/next/close函数用法详解 大家好&#xff0c;我是艾西&#xff0c;今天跟大家讲解下仙境传说mes/next/close函数&#xff0c;在游戏中所有的NPC对话都是用mes函数来创建的。 我们先打开官方文档的script _commands.txt文件&#xff0c;搜索*mes searc…

mmdetection调用模型训练

mmdetection调用模型训练 文章目录 mmdetection调用模型训练转化数据集格式从labelme到coco首先data导进来改一下coco.py改一下class_names.py在模型跑了之后看生成文件然后掐了包版本设置PYTHONPATHdiffustiondet模型模型训练跑完了检测模型 yolo模型yolof模型 转化数据集格式…

qemu arm-trusted-firmware atf 的编译

参考网站 ATF (arm-trusted-firmware&#xff09;&#xff0c;可以称之为 Trusted Firmware-A (TF-A)&#xff0c;也就是 TF-A https://www.trustedfirmware.org/ https://github.com/ARM-software/arm-trusted-firmware 环境 使用 qemu&#xff0c;就是不需要板子 win10 …

Node.js入门与 Webpack模块打包工具

目录 Node.js入门 fs模块-读写文件 path模块-路径处理 压缩前端html 认识URL中的端口号 http模块-创建Web服务 体验 Web 服务除了接口数据以外&#xff0c;还能返回网页资源等 Node.js模块化 ECMAScript标准-默认导出和导入 ECMAScript标准-命名导出和导入 包的…

攻防世界-Reverse-Game

题目描述&#xff1a;下载附件&#xff0c;得到一个exe程序&#xff0c;运行该程序&#xff0c;可以看到如下的界面 根据描述信息说明&#xff1a; a. 这是一个电路&#xff0c;有8个开关&#xff0c;只有8个开关全部闭合&#xff0c;才能够获取到flag&#xff1b; b. 其中n表…