数据结构之堆(topk问题、堆排序)

一、堆的初步认识

堆虽然是用数组存储数据的数据结构,但是它的底层却是另一种表现形式。

堆分为大堆和小堆,大堆是所有父亲大于孩子,小堆是所有孩子大于父亲。

 通过分析我们能得出父子关系的计算公式,parent=(child-1)/2,左孩子leftchild=parent*2+1,右孩子rightchild=parent*2+2,这会在下面实现时应用。

二、堆实现

1、头文件

#pragma once
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
#include<stdbool.h>typedef int HPDataType;typedef struct Heap
{HPDataType* a;int size;int capacity;
}HP;void HeapPrint(HP* php);//堆打印
void HeapInit(HP* php);//堆初始化
void HeapPush(HP* php, HPDataType x);//堆插入
void HeapPop(HP* php);//堆删除
HPDataType HeapTop(HP* php);//返回堆顶元素
bool HeapEmpty(HP* php);//判空
int HeapSize(HP* php);//返回堆大小
void AdjustUp(HPDataType* a, int child);//向上调整
void AdjustDown(HPDataType* a, int n, int parent);//向下调整
void Swap(HPDataType* x, HPDataType* y);//交换函数
void HeapSort(int* arr, int n);//堆排序
void HeadDestroy(HP* php);//堆销毁

这里用结构体管理数据,HPDataType*a是动态数组的指针,HPDataType是typedef定义的可变参数,需要更改存储类型时,修改typedef的内容即可,size用于统计存储数据的多少,capacity是统计开辟的空间大小,即动态申请数组的大小。 

2、 堆初始化

void HeapInit(HP* php)
{assert(php);php->a = (HPDataType*)malloc(sizeof(HPDataType)* 4);if (php->a == NULL){perror("malloc fail");return;}php->size = 0;php->capacity = 4;
}

assert检查指针是否为空,malloc动态申请空间,然后对size和capacity(空间的大小)初始化 

3、堆打印

void HeapPrint(HP* php)
{for (int i = 0; i < php->size; i++){printf("%d ", php->a[i]);}printf("\n");
}

 4、向上调整

void AdjustUp(HPDataType* a, int child)
{int parent = (child - 1) / 2;/*while (a[parent] < a[child]){Swap(&a[parent], &a[child]);child = parent;parent = (child - 1) / 2;}*/while (child > 0) //与下面风格相同{if (a[child] > a[parent]){Swap(&a[child], &a[parent]);child = parent;parent = (child - 1) / 2;}else break;}
}

向上调整用于解决插入数据造成的不构成堆的问题 

5、堆插入

当我们插入一个值时,这个新插入的值也许会破坏原本的堆关系,所以我们需要进行向上调整,使其恢复堆关系。 

void HeapPush(HP* php, HPDataType x)
{assert(php);if (php->size == php->capacity){HPDataType* tmp = (HPDataType*)realloc(php->a, sizeof(HPDataType)* php->capacity * 2);if (tmp == NULL){perror("realloc fail");return;}php->a = tmp;php->capacity *= 2;}php->a[php->size] = x;//size代表元素个数,a[size]为下一个元素php->size++;AdjustUp(php->a, php->size - 1);//向上调整
}

 6、向下调整

void AdjustDown(HPDataType* a,int n ,int parent)
{/*int child = a[parent * 2 + 1] > a[parent * 2 + 2] ? parent * 2 + 1 : parent * 2 + 2;while (child < n){Swap(&a[parent], &a[child]);parent = child;child = a[parent * 2 + 1] > a[parent * 2 + 2] ? parent * 2 + 1 : parent * 2 + 2;}*/int child = parent * 2 + 1;//左孩子while (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;}
}

7、堆删除

这里选择堆顶元素和堆底元素交换,如果挪动数据会导致父子关系乱套,而这里不free最后一个元素,避免释放后继续使用。

void HeapPop(HP* php)
{assert(php);assert(!HeapEmpty(php));//挪动删除:1.效率低下2.关系全乱//只需要交换第一个元素和最后一个元素值,并php->size--//1.效率高2.保持父子关系Swap(&php->a[0], &php->a[php->size - 1]);php->size--;AdjustDown(php->a, php->size, 0);}

 8、返回堆顶元素

HPDataType HeapTop(HP* php)
{assert(php);return php->a[0];
}

动态数组中存储的第一个元素就是堆顶元素  

9、堆判空

bool HeapEmpty(HP* php)
{assert(php);return php->size == 0;
}

通过size的数量判空,如果为0,则堆为空,返回true 

 10、堆大小

int HeapSize(HP* php)
{assert(php);return php->size;
}

 这里结构体中有size数据,返回即可。

11、堆销毁

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

 free掉a指针指向的空间,a指针置空,size和capacity赋值0.

三、扩展

1、堆排序(升序大堆,降序小堆)

时间复杂度O(N*logN)

先对要排序的数组建堆,然后交换堆顶元素,对剩余的元素向下调整。

void HeapSort(int* arr, int n)
{for (int i = (n-2)/2; i >0; i--){AdjustDown(arr, n, i);}int end = n - 1;while (end){Swap(&arr[0], &arr[end]);AdjustDown(arr, end, 0);end--;}
}

2、topk问题

 用k个元素建小堆,剩余n-k个元素与堆顶元素比较交换即可,最后k大小的小堆中保留的是这n个数中前k个最大的数。

看到最后,如果对您有所帮助,请点赞、收藏和关注,点点关注不迷路,源码已上传Gitee有需自取:白天没有黑夜 (not-during-the-day) - Gitee.com,我们下期再见!

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

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

相关文章

0基础 Git 代码操作

将代码提交仓库&#xff1a; 准备工作​ ​注册 Gitee 账号​&#xff1a;确保你已注册并登录 Gitee。​创建仓库​&#xff1a;在 Gitee 上新建一个空仓库&#xff08;如果尚未创建&#xff09;&#xff1a; 点击右上角 → 新建仓库。填写仓库名称、描述&#xff0c;选择公…

OpenAI大模型不听人类指令事件的技术分析与安全影响

OpenAI大模型不听人类指令事件的技术分析与安全影响 OpenAI大模型o3确实存在不遵从人类关闭指令的现象&#xff0c;这一行为已被第三方安全机构验证&#xff0c;但其本质是技术缺陷而非AI意识觉醒。帕利塞德研究所的测试显示&#xff0c;在100次实验中o3有7次成功绕过关闭指令…

软件工程期末速成--附带几道题

软件工程中的各种设计 瀑布模型&#xff1a; 定义&#xff1a;将软件生存周期的各项活动规定为依照固定顺序连接的若干阶段工作&#xff0c;形如瀑布流水&#xff0c;最终得到软件产品 系统流程图&#xff1a;系统流程图是描绘物理系统的传统工具&#xff0c;它的基本思想是用…

免费分享50本web全栈学习电子书

最近搞到一套非常不错的 Web 全栈电子书合集&#xff0c;整整 50 本&#xff0c;都是epub电子书格式&#xff0c;相当赞&#xff01;作为一个被期末大作业和项目 ddl 追着跑的大学生&#xff0c;这套书真的救我狗命&#xff01; 刚接触 Web 开发的时候&#xff0c;我天天对着空…

嵌入式学习笔记——day26

文件操作&#xff08;续&#xff09;目录操作 一、文件操作 1. lseek lseek 是一个用于在文件中移动文件指针的系统调用&#xff0c;通常用于在文件描述符所指向的文件中定位读取或写入的位置。它允许程序在文件中随机访问数据&#xff0c;而不是只能顺序读取或写入。 off_t …

LINUX安装运行jeelowcode前端项目

参考 JeeLowCode低代码社区,JeeLowCode低代码开发平台,JeeLowCode低代码开发框架,快速启动&#xff08;VUE&#xff09; 安装node 18 LINUX安装node/nodejs_linux安装node 安装到哪-CSDN博客 安装PNPM LINUX安装PNPM-CSDN博客 下载 git clone https://gitcode.com/jeelo…

【Redis】基本架构

1. 单线程模型 现在开启了三个redis-cli客户端同时执行命令。 客户端1设置一个字符串键值对&#xff1a; 127.0.0.1:6379> set hello world客户端2对counter做自增操作&#xff1a; 127.0.0.1:6379> incr counter客户端3对counter做自增操作&#xff1a; 127.0.0.1:…

[yolov11改进系列]基于yolov11的修改检测头为自适应特征融合模块为ASFFHead检测头的python源码+训练源码

【自适应空间特征融合模块ASFF介绍】 ASFF&#xff08;Adaptive Spatial Feature Fusion&#xff09;是一种自适应特征融合策略&#xff0c;旨在解决目标检测中不同尺度特征之间的冲突和不一致性。 ‌ 基本概念和原理 ASFF通过学习每个尺度特征的自适应融合权重&#xff0c…

机器学习——支持向量机SVM

机器学习——支持向量机 一、介绍1.概述1.1 概念1.2 SVM的优缺点 2.硬间隔2.1 求解间隔2.2 对偶问题 3.软间隔3.1 松驰变量3.2 对偶问题 4.核函数4.1 概念4.2 常见的核函数 二、代码实战1.实验要求2.具体实现2.1 词汇表加载2.2 邮件预处理函数2.3词索引转换为特征向量2.4 SVM 模…

Python 科学计算有哪些提高运算速度的技巧

在科学计算中提高 Python 运算速度的核心技巧包括&#xff1a;使用 NumPy 向量化操作、利用 Numba 加速函数、调用 C/C 扩展模块、应用多线程/多进程并行计算、使用 GPU 加速计算。其中&#xff0c;使用 NumPy 向量化是最基础且见效最快的优化方式。NumPy 利用底层 C 实现高效的…

React+Antd全局加载遮罩工具

下面是全局加载遮罩工具&#xff0c;功能&#xff1a;提供show和showWithDelay/hide方法用于显示/延时显示/隐藏遮罩&#xff0c;它还提供loading属性返回是否正在loading。通常用于耗时较长的操作&#xff0c;比如远端api调用。 如何用它&#xff0c;下面是个例子&#xff0c…

【机器学习基础】机器学习入门核心算法:GBDT(Gradient Boosting Decision Tree)

机器学习入门核心算法&#xff1a;GBDT&#xff08;Gradient Boosting Decision Tree&#xff09; 1. 算法逻辑2. 算法原理与数学推导2.1 目标函数2.2 负梯度计算2.3 决策树拟合2.4 叶子权重计算2.5 模型更新 3. 模型评估评估指标防止过拟合 4. 应用案例4.1 金融风控4.2 推荐系…

水墨色调中国风PPT模版分享

水墨色调中国风PPT模版分享&#xff1a;水墨中国风PPT模版https://pan.quark.cn/s/4368c537b1d2 第一套PPT模版​&#xff1a;主题是“爱莲说”&#xff0c;水墨风格封面。核心视觉是绿色莲蓬、白鹤、红色印章&#xff0c;文字有“爱莲说”等。适用文学或传统文化类演示。 ​第…

PBX、IP PBX、FXO 、FXS 、VOIP、SIP 的概念解析以及关系

PBX&#xff08;Private Branch Exchange&#xff09; 概念 &#xff1a;PBX 是专用交换机&#xff0c;是一种在企业或组织内部使用的电话交换系统。它允许内部用户之间以及内部用户与外部公共电话网络&#xff08;PSTN&#xff09;之间进行通信。例如&#xff0c;在一个大型企…

LabVIEW双光子荧光成像软件开发

双光子荧光成像技术在抑郁小鼠脑内丙二醛&#xff08;MDA&#xff09;和甲醛&#xff08;FA&#xff09;检测中的软件开发&#xff0c;基于 LabVIEW 平台构建从硬件控制、数据采集到图像处理的全流程系统。结合 5734 FPGA 实现实时图像处理&#xff0c;突出双光子成像的深度开发…

OSI模型中的网络协议

一、电子邮件协议&#xff1a;从SMTP到MIME的扩展 电子邮件系统的核心协议包括SMTP&#xff08;Simple Mail Transfer Protocol&#xff09;、POP3&#xff08;Post Office Protocol&#xff09;和IMAP&#xff08;Internet Message Access Protocol&#xff09;&#xff0c;但…

流程自动化引擎:让业务自己奔跑

在当今竞争激烈的商业环境中&#xff0c;企业面临着快速变化的市场需求、日益复杂的业务流程以及不断增长的运营成本。如何优化业务流程、提升效率并降低成本&#xff0c;成为企业持续发展的关键问题。 流程自动化引擎&#xff08;Process Automation Engine&#xff09;作为一…

DNS解析过程以及使用的协议名称

DNS&#xff08;Domain Name System 域名系统&#xff09;解析是一个分层查询的过程 1.本地缓存查询阶段 先检查浏览器自身的DNS缓存 接着检查操作系统的DNS缓存 最后检查本地 hosts 文件 2.本地DNS服务器查询阶段 先向本地DNS服务器查询&#xff0c;协议是 DNS over UDP&a…

思澈科技助力Keep Watch Pilot 1:重新定义智能运动手表体验

——以创新芯片技术&#xff0c;打造长续航、高性能的随身运动教练 作为智能穿戴领域的核心技术支持者&#xff0c;思澈科技携手Keep共同推出全新智能运动手表Keep Watch Pilot 1。该产品搭载思澈科技自主研发的SF32LB557芯片&#xff0c;在高性能显示、超长续航与精准运动监测…

github actions入门指南

GitHub Actions 是 GitHub 提供的持续集成和持续交付&#xff08;CI/CD&#xff09;平台&#xff0c;允许开发者自动化软件工作流程&#xff08;如构建、测试、部署&#xff09;。以下是详细介绍&#xff1a; 一、核心概念 Workflow&#xff08;工作流程&#xff09; 持续集成的…