当前位置: 首页 > news >正文

二叉树堆的建立与排序

在数据结构中,二叉树是非常好用的一种数据结构,这节暂时按下不表。这节课主要介绍堆的建立与使用。

堆,是二叉树中一种很特殊的结构,首先,他必须是满二叉树,也就是除了最后一层以外,其他层都是满的。

堆对于节点数据也有要求,其基本按照某种规律进行排序。首先堆分为大堆和小堆。大堆上大小大小堆上小下大。有非常大的差距。并且在堆中每个节点也满足完全二叉树的父子节点规律,既child=parent*2+1 | 2,1和2取决于是子左节点还是右节点。

堆的实现


typedef int HPDataType;
typedef struct Heap
{HPDataType* _a;int _size;int _capacity;
}Heap;//child = father*2+1 | 2;

一个堆的基本结构体如上图所示,它应该有一个特定类型的指针_a,一个代表堆目前数量的size,一个代表目前容量的_capacity。为什么选择顺序表作为建堆类型呢?首先是因为堆不需要在中间插入数据,他是满二叉树;第二是因为利用数组来建队可以发现数组的下标之间的关系,就是这个公式:child=parent*2+1 | 2,便于进行计算。本文前半部分基本以小堆为准。

堆的初始化

void HeapInit(Heap* php)
{assert(php);php->_a = NULL;php->_capacity = 0;php->_size = 0;
}//函数初始化Heap* HeapKCreat(int k)
{Heap* hp = (Heap*)malloc(sizeof(Heap));if (hp == NULL){perror("fail:hp creat");exit(1);}int* arr = (int*)malloc(sizeof(int) * k);hp->_a = arr;hp->_size = 0;hp->_capacity = 0;return hp;
}函数创建

堆的创建分为两种方式,一种是在外面申请空间,然后再函数内设置数据,一种是直接在函数内部完成一切,总体而言还是简单的把相关数据进行简单设置。

堆的销毁

void HeapDestory(Heap* hp)
{assert(hp);free(hp->_a);hp->_a = NULL;hp->_capacity = hp->_size = 0;
}

堆的销毁也较为简单,便是顺序表的销毁。其中有一个地方需要注意,便是需要先把数组给free掉。

堆的两种整理方式

void AdjustUp(HPDataType* obj, int child)
{int parent = (child - 1) / 2;while (obj[parent] > obj[child] && child > 0){Swap(&obj[child], &obj[parent]);child = parent;parent = (child - 1) / 2;}
}

第一个函数是从下往上整理,先设置一个parent变量,这个变量便是孩子的父节点,因为/操作符的整除性,所以会自动得到对应节点。接着比较子节点大小与父节点大小的,若父节点大于子节点,那就父子对换,并让子为父,在重新设置父节点。一直到父节点不再大于子节点或者子节点到了顶部。

void AdjustDowm(HPDataType* obj, int n, int parent)
{int child = parent * 2 + 1;while (child < n){if (obj[child + 1] < obj[child] && child + 1 < n){child++;}if (obj[parent] > obj[child]){Swap(&obj[child], &obj[parent]);parent = child;child = parent * 2 + 1;}elsebreak;}
}

另一种方案是从上往下整理,同样的初始造个儿子操作。接着,判断儿子不要超过数组数据大小范围,这个设置出来的儿子是左儿子,接着判断右儿子和左儿子的大小关系.若是右儿子要大一些的话,那就让右儿子来和父节点较量较量。接着,若父节点大于子节点的话,那便换位置。一直到循环结束。

这两种方法总体而言方法二会更好一点,方法二的时间复杂度为O(logN),方法一为O(N).具体计算方法可以上b站查一下。

堆的数据增加

void HeapPush(Heap* hp, HPDataType x)
{assert(hp);if (hp->_capacity == hp->_size){int newcapacity = hp->_capacity == 0 ? 4 : hp->_capacity * 2;HPDataType* b = (HPDataType*)realloc(hp->_a, newcapacity * sizeof(HPDataType));if (b == NULL){exit(1);}hp->_a = b;hp->_capacity = newcapacity;}hp->_a[hp->_size] = x;hp->_size++;AdjustUp(hp->_a, hp->_size - 1);
}

堆的push首先断言一下,防止输入的结构体为空。接着,若此时容量等于当前数据量,那么会进入扩容阶段。此处建立一个一个newcapacity,利用三目操作符,如果此时容量大小为0,那么调整为4,若不是0,那么扩容两倍。接着realloc一个新的结构体指针,其大小便是调整后的新容量。接着在判断一下realloc是否成功,接着将realloc出来的指针给结构体中的_a指针,然后吧容量变为新的容量。接着就开始进行赋值,把数据x放在数组的最后一个空地址,接着将size++。再然后向上调整或者向下调整都是可以的。这里便选择了向上调整了。

堆的删除

void HeapPop(Heap* hp)
{assert(hp);assert(hp->_size > 0);Swap(&hp->_a[0], &hp->_a[hp->_size - 1]);hp->_size--;AdjustDowm(hp->_a, hp->_size, 0);}

堆的删除首先要先确定不是空指针和堆里确实有数据。接着交换一下堆顶数据和堆底数据。将hp的size--,保证后续读取不到要删除的数据。接着将堆顶数据向下调整即可。

堆的部分简单判断与取数据

HPDataType HeapTop(Heap* hp)
{assert(hp);assert(hp->_size > 0);return hp->_a[0];
}//取堆顶数据int HeapSize(Heap* hp)
{assert(hp);return hp->_size;
}取堆大小int HeapEmpty(Heap* hp)
{assert(hp);return hp->_size == 0;
}判断堆是否空了

堆的排序

void HeapSort(int* a, int n)
{//for (int i = 0; i < n; i++)//{//	AdjustUp(a, a[i]);//}空间要求较多,建议从下往上整,既下面方案int end = n - 1;while (end--)//{Swap(&a[0], &a[end]);AdjustDowm(a, n, 0);}
}

说是堆的排序,但其实针对于任何混乱的数组,将他们整理成有序的堆。堆的排序分为两种方式,第一种方法是从上面的代码,但是其堆空间的要求较多,因此较为推荐下面的方法。

TopK问题

我们建堆是为了什么呢?建堆一个很重要的意义便是找出最大的几个数据或者最小的几个数据。一个很大的数据本,要求前k个最大的数据,可以通过什么方法呢?一个相对好用的方法就是通过建容量为k的小堆,然后逐渐替换堆内的数据来达成这个容量为k的小堆内的数据便是原数据库的前k个最大的数据。具体实现过程如下

创建数据库

void CreateNDate()
{// 造数据int n = 100000;srand(time(0));const char* file = "data.txt";FILE* fin = fopen(file, "w");if (fin == NULL){perror("fopen error");return;}for (size_t i = 0; i < n; ++i){int x = rand() % 1000000;fprintf(fin, "%d\n", x);}fclose(fin);
}

首先我们先来利用time的伪随机来创建一个数据库,内部包含10万个随机的数据,并将这些数据写入名字为data的txt文件,这就是我们后面用来举例的数据库了。

topk数据库

void PrintTopK(int k)
{int* arr = (int*)malloc(sizeof(int)*k);char* file = "data.txt";FILE* fin = fopen(file, "r");for (int i = 0; i < k; i++){fscanf(fin, "%d ",&arr[i]);}int a = 0;while (fscanf(fin, "%d ", &a)!=EOF) {if (a > arr[0]){arr[0] = a;AdjustDowm(arr,k,0);}}for (int i = 0; i < k; i++){printf("%d ", arr[i]);}}

首先,我们需要先创建出一个容量符合小堆的数组,因为我这里的数据都是整型,因此便直接使用int类型了。接着打开data文件,首先将data中前10个数据写入arr数组,接着设置一个普普通通的int类型数据a,接着进入while循环,fscanf会返回读到的数据数量,当没有数据的时候,则返回EOF,当还有数据的时候,将数据写入a中,判断a和arr[0]的大小关系。若arr[0]小于a,则将a写入数组中成为堆顶。接着向下调整刚刚写入的数据。直到已经将data文件中的数据全部读了一遍,此时数组中包含的数据便是所有的最大数据。接着将这些数据打印出来,便得到了TopK个数据了。

相关文章:

二叉树堆的建立与排序

在数据结构中&#xff0c;二叉树是非常好用的一种数据结构&#xff0c;这节暂时按下不表。这节课主要介绍堆的建立与使用。 堆&#xff0c;是二叉树中一种很特殊的结构&#xff0c;首先&#xff0c;他必须是满二叉树&#xff0c;也就是除了最后一层以外&#xff0c;其他层都是…...

【软件测试】Bug 篇

哈喽&#xff0c;哈喽&#xff0c;大家好~ 我是你们的老朋友&#xff1a;保护小周ღ 今天给大家带来的是 【软件测试】Bug 篇&#xff0c;首先了解, 什么是Bug, 如何定义一个Bug, 如何描述一个 Bug, Bug的级别, 和 Bug 的生命周期, 以及测试人员跟开发人员产生争执如何处理,…...

oracle 多表查询

3.6多表查询 当查询的数据并不是来源一个表时&#xff0c;需要使用多表连接操作完成查询。多表连接查询通过表之间的关联字段&#xff0c;一次查询出多个表的数据。 3.6.1等值连接 等值连接也称为简单连接(Simple Joins)或者内连接(Inner Join)。通过等号来判断连接条件中的数据…...

layui 可以使点击图片放大

layui可以使图片点击放大&#xff0c;不用在写jquyery了真是很方便。 操作示例 引入 <link rel"stylesheet" href"https://cdn.jsdelivr.net/npm/layui-layer3.1.1/dist/layui.css" /> <script src"https://cdn.bootcdn.net/ajax/libs/jqu…...

制作网上3D展馆需要什么技术并投入多少费用?

制作网上3D展览馆项目&#xff0c;需要考虑以下技术和预算方面的信息&#xff1a; 技术需求&#xff1a; 1、三维建模技术&#xff1a;利用3D软件&#xff08;3ds max、maya、blender、c4d等&#xff09;制作展馆和展品的3D模型 2、Web3D技术&#xff1a;如WebGL&#xff0c…...

C++标准库容器类——string类

引言 在c中&#xff0c;string类的引用极大地简化了字符串的操作和管理&#xff0c;相比 C 风格字符串&#xff08;char*或cahr[]&#xff09;&#xff0c;std::string 提供了更高效和更安全的字符串操作。接下来让我们一起来深入学习string类吧&#xff01; 1.string 的构造…...

Qt --- 常用控件的介绍 --- 其他控件

一、QPushButton QWidget中设计到的各种属性/函数/使用方法&#xff0c;针对接下来要介绍的Qt的各种控件都是有效的。 使用QPushButton表示一个按钮&#xff0c;这也是当前我们最熟悉的一个控件了。这个类继承了QAbstractButton&#xff0c;这个类是一个抽象类&#xff0c;是…...

spark读取数据性能提升

1. 背景 spark默认的jdbc只会用单task读取数据&#xff0c;读取大数据量时&#xff0c;效率低。 2. 解决方案 根据分区字段&#xff0c;如日期进行划分&#xff0c;增加task数量提升效率。 /*** 返回每个task按时间段划分的过滤语句* param startDate* param endDate* param …...

一次使用threading.Thread来实现Pytorch多个模型并发运行的失败案例

文章目录 背景我的做法&#xff08;但证明不起效果&#xff09; 背景 我有多个pytorch GPU模型&#xff0c;他们有不同的参数&#xff08;也就是说不是共享的&#xff09;&#xff0c;但是相同的数据输入&#xff0c;想要并发运行。 不并发运行&#xff0c;当然就是循环喽。 …...

HashMap源码

简介 HashMap 是一种基于哈希表的 Map 接口实现&#xff0c;它存储键值对&#xff08;key-value pairs&#xff09;&#xff0c;并允许使用键来快速检索值。在 Java 中&#xff0c;HashMap 是 java.util 包的一部分&#xff0c;它不是同步的&#xff0c;这意味着它不是线程安全…...

探索 Web Speech API:实现浏览器语音识别与合成

引言 Web Speech API 是一项由 W3C 开发的 Web 标准&#xff0c;为开发者提供了在 Web 应用程序中实现语音识别和语音合成的能力。通过 Web Speech API&#xff0c;我们可以让网页与用户进行语音交互&#xff0c;实现更加智能化和便捷的用户体验。本文将深入探讨 Web Speech A…...

python基础题练习

1.可否定义一个sum函数呢&#xff1f;返回指定区间的值的和&#xff1f;例如&#xff0c;区间[1,4]的和为123410返回指定区间值的平方的和呢&#xff1f;立方呢&#xff1f; 代码&#xff1a; # 计算从start到end&#xff08;包括end&#xff09;的所有整数的和。 def sum_ra…...

工业交换机如何保证数据的访问安全

在现代工业自动化环境中&#xff0c;工业交换机作为关键的网络设备&#xff0c;扮演着数据传输和信息交互的重要角色。为了确保数据的访问安全&#xff0c;工业交换机不仅具备高效的转发性能&#xff0c;还集成了多层次的安全防护机制&#xff0c;以抵御各种潜在的网络威胁。 首…...

jmeter得到的文档数据处理

通过前面jmeter得到的输出文档&#xff0c;这里是txt文档&#xff0c;里面包含了很多条数据&#xff0c;每条数据的结构如下&#xff1a; 【request】 uuid&#xff1a;xxxxxxx timestamp&#xff1a;xxxxxxxx No.x question&#xff1a;xxxxxxx 【response】 code&#…...

12- 【JavaWeb】校园快递管理系统-数据库建设

项目概述 开发一个Javaweb校园快递管理系统&#xff0c;包含以下功能&#xff1a; 数据库设计 首先,我们需要设计数据库的表结构。主要包括以下表: 学生表: 存储学生的基本信息&#xff0c;姓名、手机号。快递表: 存储快递的信息&#xff0c;快递单号、收件人、收件人手机号、…...

Windows本地连接远程服务器并创建新用户详细记录

前提可知&#xff1a; &#xff08;1&#xff09;服务器IP地址&#xff1a;x.x.x.x &#xff08;2&#xff09;服务器名称&#xff1a;root&#xff08;一般默认为root&#xff0c;当然也有别的名称&#xff09; &#xff08;3&#xff09;服务器登陆密码&#xff1a;**** 一、…...

【kaggle竞赛】毒蘑菇的二元预测题目相关信息和思路求解代码

毒蘑菇的二元预测 您提供了很多关于不同二元分类任务的资源和链接&#xff0c;看起来这些都是Kaggle竞赛中的参考资料和高分解决方案。为了帮助您更好地利用这些资源&#xff0c;这里是一些关键点的总结&#xff1a; Playground Season 4 Episode 8 主要关注的竞赛: 使用银行…...

Pytest-allure如何在测试完成后自动生成完整报告?

一、完整步骤 常规allure报告的生成方法是在pytest全部用例执行完成后&#xff0c;手动在命令行执行如 allure generate ./temps -o ./report --clean每次用例执行完成后都要重复如此的操作&#xff0c;十分繁琐。 可以使用如下方式让用例执行完成后自动生成报告到当前目录下…...

数据结构-树(基础,分类,遍历)

数据结构-树 1.什么是树&#xff1f; 在计算机科学中&#xff0c;树是一种常用的非线性数据结构&#xff0c;用于表示具有层次关系的数据。与线性数据结构&#xff08;如数组和链表&#xff09;不同&#xff0c;树结构以节点&#xff08;Nodes&#xff09;和边&#xff08;Ed…...

CodeGeeX4:程序员的高效助手,多语言代码生成神器!

你是否曾在编写代码时&#xff0c;为复杂的语法、逻辑错误而绞尽脑汁&#xff1f;或是在面对多个编程语言的切换时&#xff0c;感觉脑子快要爆炸&#xff1f;别担心&#xff01;一款全新的多语言代码生成神器——CodeGeeX4&#xff0c;正悄然成为程序员们的“救命稻草”。它不仅…...

什么时候Agent能自己写skill?从极客视角看AI智能体自主进化与实在Agent落地实践

关于人工智能智能体&#xff08;AI Agent&#xff09;何时能够自主编写技能&#xff08;Skill&#xff09;这一课题&#xff0c;根据2026年4月1日的最新科技前沿动态分析&#xff0c;我们正处于从“人工定义技能”向“智能体自主生成与进化技能”跨越的关键转折点。当前的行业共…...

WebDAV网盘横向评测:从个人备份到多端同步的实战指南

1. WebDAV网盘入门&#xff1a;为什么你需要它&#xff1f; 刚接触WebDAV时&#xff0c;我和大多数人一样疑惑&#xff1a;明明有那么多现成的网盘&#xff0c;为什么还要折腾这个&#xff1f;直到有次出差&#xff0c;急需修改存放在某商业网盘里的设计方案&#xff0c;却发现…...

3个步骤实现极致跨平台远程控制:BilldDesk Pro突破性体验

3个步骤实现极致跨平台远程控制&#xff1a;BilldDesk Pro突破性体验 【免费下载链接】billd-desk 基于Vue3 WebRTC Nodejs Flutter搭建的远程桌面控制 项目地址: https://gitcode.com/gh_mirrors/bi/billd-desk 还在为远程协作的种种限制而烦恼吗&#xff1f;当你需…...

ai辅助c++开发:让快马成为你的codeblocks智能编程助手与算法导师

AI辅助C开发&#xff1a;让快马成为你的CodeBlocks智能编程助手与算法导师 最近在用CodeBlocks开发一个C图形化应用时&#xff0c;遇到了一个典型问题&#xff1a;需要实现非递归快速排序算法并测试性能。传统开发方式可能需要反复查阅文档、调试代码&#xff0c;但借助InsCod…...

3个维度玩转League-Toolkit:从入门到精通的实战指南

3个维度玩转League-Toolkit&#xff1a;从入门到精通的实战指南 【免费下载链接】League-Toolkit 兴趣使然的、简单易用的英雄联盟工具集。支持战绩查询、自动秒选等功能。基于 LCU API。 项目地址: https://gitcode.com/gh_mirrors/le/League-Toolkit League-Toolkit是…...

MLCC陶瓷电容选型避坑指南:从X7R到C0G,5个关键参数决定电路稳定性

MLCC陶瓷电容选型避坑指南&#xff1a;从X7R到C0G&#xff0c;5个关键参数决定电路稳定性 当你在设计一个精密电源模块时&#xff0c;突然发现输出电压在高温环境下出现异常波动&#xff1b;或者调试射频电路时&#xff0c;明明计算无误的滤波网络却始终达不到预期效果——这些…...

DSQC346G 3HAB8101-8 机器人伺服驱动单元

DSQC346G 3HAB8101‑8 机器人伺服驱动单元介绍DSQC346G&#xff08;3HAB8101‑8&#xff09;是一款专用于工业机器人伺服系统的驱动单元&#xff0c;用于控制伺服电机的运动与输出&#xff0c;实现机器人关节或轴的精确位置、速度和力矩控制&#xff0c;是机器人驱动链中的核心…...

保姆级教程:手把手教你用Python+Control库仿真PLL噪声传递函数

保姆级教程&#xff1a;手把手教你用PythonControl库仿真PLL噪声传递函数 锁相环&#xff08;PLL&#xff09;作为现代电子系统中的核心组件&#xff0c;其噪声特性直接影响通信质量、时钟精度等关键指标。但教科书上复杂的传递函数公式总让人望而生畏——直到你发现用几行Pyth…...

在大厂工作,一旦开窍后,你会爽死…

在职场尤其是大厂里&#xff0c;沟通能力往往比硬实力更能决定你的发展节奏。很多时候&#xff0c;同样一件事&#xff0c;不同的说法&#xff0c;会带来完全不同的结果。下面这8个高频职场场景&#xff0c;对应的高情商话术&#xff0c;帮你轻松化解尴尬、刷好感&#xff0c;还…...

HighwayEnv完全指南:10分钟快速上手自动驾驶强化学习环境

HighwayEnv完全指南&#xff1a;10分钟快速上手自动驾驶强化学习环境 【免费下载链接】HighwayEnv A minimalist environment for decision-making in autonomous driving 项目地址: https://gitcode.com/gh_mirrors/hi/HighwayEnv HighwayEnv是一个轻量级的自动驾驶决…...