【数据结构】(堆)Top-k|堆排序

目录

概念:

堆的实现 

构建

初始化

销毁

插入元素

往上调整 

删除堆顶元素 

往下调整 

返回堆顶元素 

 返回有效个数

是否为空

 堆排序

 Top-k问题

​编辑 创建数据

堆top-k


概念:

堆是将数据按照完全二叉树存储方式存储到一维数组中;

堆分为大堆和小堆:

大堆:父结点大于等于孩子结点;

小堆:父结点小于等于孩子结点;

父结点与(左右)孩子结点关系:

1.父结点 = (孩子结点-1)/2;

2.左结点= (父结点*2)+1;

        右结点= (父结点*2)+2;

堆的实现 

堆的逻辑结构是完全二叉树,物理结构是一维数组存储;

而独特的结点关系,堆排序也是一种选择排序,

构建

typedef int HPDataType;
typedef struct Heap
{HPDataType* parr;int size;		//存储的有效数据个数int capacity;	//容量
}Heap;
//	用数组存储    

初始化

//堆的初始化
void HeapInit(Heap* php)
{assert(php);php->parr = NULL;php->size = 0;php->capacity = 0;
}

销毁


//堆的销毁
void HeapDestroy(Heap* php)
{assert(php);free(php->parr);php->parr = NULL;php->size = php->capacity = 0;free(php);php = NULL;
}

插入元素

因为堆分为两类,在数据插入时,需要选择适应的调整;

以小堆来说:当插入一个新元素时,插入到堆尾,与父结点比较,相应的往上调整

//堆的插入元素
void HeapPush(Heap* php, HPDataType x)
{assert(php);//检查容量if (php->size == php->capacity){int newcapacity = php->capacity == 0 ? 4 : php->capacity * 2;HPDataType* newparr = (HPDataType*)realloc(php->parr, sizeof(HPDataType) * newcapacity);if (newparr == NULL){perror("realloc fail");exit(-1);}php->capacity = newcapacity;php->parr = newparr;}php->parr[php->size] = x;php->size++;//小堆//向上调整AdjustUp(php->parr, php->size - 1);
}

往上调整 

当插入一个新元素,按照孩子和父结点之间的关系进行比较,交换两结点数据,直到满足堆的性质 

//向上调整
void AdjustUp(HPDataType* parr,int size)
{int child = size;int parent = (child - 1) / 2;//小堆=> 父结点<=孩子结点while (child>0){if (parr[child] < parr[parent]){//交换数据Swap(&parr[child], &parr[parent]);child = parent;        //更新结点位置parent = (child - 1) / 2;}else{break;}}
}

删除堆顶元素 

1.将堆顶元素和尾部元素互换位置;

2.将此刻不符合规定的堆顶元素往下调整至相应位置; 

// 删除堆顶(根节点)
void HeapPop(Heap* php)
{assert(php);//1.堆顶元素和尾部元素置换位置Swap(&php->parr[0], &php->parr[php->size - 1]);php->size--;	//删掉交换后的堆顶元素//2.将新站顶元素找到相应位置//向下调整AdjustDown(php->parr,php->size,0);
}

往下调整 

堆顶元素与其孩子结点比较,如何找到较大(较小)的孩子?

可以假设法:假设较大(较小)的孩子为左孩子,然后验证假设;

//向下调整
void AdjustDown(HPDataType* parr,int size,int parent)
{int child = (parent * 2) + 1;while (child<size)	//{//假设左孩子为较小值if (child+1<size && parr[child + 1] < parr[child])	//验证假设{++child;	//说明右孩子更小,更换孩子位置}//检查是否不符合堆排序结构 if (parr[parent] > parr[child]){Swap(&parr[parent], &parr[child]);//往下更新父结点 孩子结点位置parent = child;child = parent * 2 + 1;}else{break;}}
}

返回堆顶元素 

起始值为0;

//返回堆顶元素
HPDataType HeapTop(Heap* php)
{assert(php);assert(php->size > 0);return php->parr[0];
}

 返回有效个数

注意,构建堆的时候,size是最后一个元素的下一个;

//返回堆内有效数据个数
size_t HeapSize(Heap* php)
{assert(php);return php->size;	//数组下标0开始
}

是否为空

//判断堆是否为空
bool HeapEmpty(Heap* php)
{return php->size == 0;
}

 堆排序

以上是一些堆的简单功能实现;算不上真正的堆排序;

假设给定一串数字,4,6,2,1,5,8,2,9;如何将其排序?比如升序;

  1. 建立一个大堆;
  2. 将堆顶元素与堆尾元素互换,且将遍历堆的范围-1,保证其想要的值保持不动;
  3. 将此刻不符合规定的堆顶往下调整,找到次大的值;重复步骤2;

其实相当于第一个元素默认是堆,后面的进行遍历调整; 

//排序,升序
void HeapSort(int* parr, int n)
{//1.建立大堆for (int i = 1;i < n; i++){justUp(parr, i);}//2.堆顶元素与堆尾元素互换,然后将堆size-1(指只需要遍历到的位置)int end = n - 1;while (end>0){//堆顶和堆尾 元素呼唤Swap(&parr[0], &parr[end]);//往下调整justDown(parr,end,0);end--;}
}

也有其他思路;

我们从下面子树往上遍历,而内部调整时往下调整

 n-1是最后结点下标值,(结点-1)/2 可以得到该结点的父结点,从父结点往下调整;

for (int i = (n-1-1)/2; i >= 0; --i){AdjustDown(parr, n, i);}

 Top-k问题

在排序的基础上,如果这个数很大呢,比如一百万个数,要找到前k个较大值;

此刻建堆排序显然不合适;

1.读取前K个值,建立其小堆;

2.依次读取后面的值,与堆顶比较:如果比堆顶大,替换堆顶进堆,再往下调整;

 创建数据

//tok-k 问题
//创建一千万的数据
void CreateNode()
{// 造数据int n = 10000000;srand(time(0));const char* file = "data.txt";FILE* fin = fopen(file, "w");if (fin == NULL){perror("fopen error");return;}for (int i = 0; i < n; ++i){int x = (rand() + i) % 10000000;	//+i是 因为随机数产生只有三万个,加上i可以大大减少重复值fprintf(fin, "%d\n", x);}fclose(fin);
}

堆top-k

开辟K个数的空间(动态数组);

建立K个数的小堆;

读取文件中值,遍历与堆顶比较,

void HeapTok(const char* file,int k)
{FILE* fout = fopen(file, "r");if (fout == NULL){perror("fopen error");return;}//开辟K个数的空间int* minheap = (int*)malloc(sizeof(int) * k);if (minheap == NULL){perror("malloc error");return;}//建立K个数的小堆for (int i = 0; i < k; i++){//从文件流中 读取数据存到 开辟的空间中fscanf(fout,"%d", &minheap[i]);//往上调整AdjustUp(minheap, i);}//遍历文件数据 int x = 0;while (fscanf(fout, "%d", &x) != EOF)	{if (x > minheap[0]){minheap[0] = x;//往下调AdjustDown(minheap, k, 0);}}//打印tokfor (int i = 0; i < k; i++){printf("%d ", minheap[i]);}free(minheap);fclose(fout);
}

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

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

相关文章

[计网00] 计算机网络开篇导论

目录 前言 计算机网络的概念 计算机网络的分层 计算机网络的分类 网络的标准化工作和相关组织 计算机网络的性能指标 前言 计算机网络在我们的日常生活中无处不在 在网络会有各种各样的协议和封装 保证我们的信息完整,无误的在各个客户端之前传输 计算机网络的概念 四…

从文字下乡到人人学英语

从建国到改革开放&#xff0c;从恢复高考到新式教育改革&#xff0c;中国飞速发展&#xff0c;文字需求也在不断增大&#xff0c;在“地球村”的时代下&#xff0c;我们要“习文字之变&#xff0c;顺时代发展。” 古言道&#xff1a;“仓颉作书&#xff0c;后稷作稼”&#xff…

UE4 去除重复纹理

如果直接连的话&#xff0c;效果如下&#xff1a; 就存在很多重复的纹理&#xff0c;如何解决这个问题呢&#xff1f; 将同一个纹理&#xff0c;用不同的Tilling&#xff0c;将Noise进行Lerp两者之间&#xff0c;为什么要这么做呢&#xff1f;因为用一个做清晰纹理&#xff0c;…

设计模式——命令模式

引言 命令模式是一种行为设计模式&#xff0c; 它可将请求转换为一个包含与请求相关的所有信息的独立对象。 该转换让你能根据不同的请求将方法参数化、 延迟请求执行或将其放入队列中&#xff0c; 且能实现可撤销操作。 问题 假如你正在开发一款新的文字编辑器&#xff0c; …

C语言—小小圣诞树

这个代码会询问用户输入圣诞树的高度&#xff0c;然后根据输入的高度在控制台上显示相应高度的圣诞树。 #include <stdio.h>int main() {int height, spaces, stars;printf("请输入圣诞树的高度: ");scanf("%d", &height);spaces height - 1;st…

Linux---远程登录、远程拷贝命令

1. 远程登录、远程拷贝命令的介绍 命令说明ssh远程登录scp远程拷贝 2. ssh命令的使用 ssh是专门为远程登录提供的一个安全性协议&#xff0c;常用于远程登录&#xff0c;想要使用ssh服务&#xff0c;需要安装相应的服务端和客户端软件&#xff0c;当软件安装成功以后就可以使…

论文阅读《DPS-Net: Deep Polarimetric Stereo Depth Estimation》

论文地址&#xff1a;https://openaccess.thecvf.com/content/ICCV2023/html/Tian_DPS-Net_Deep_Polarimetric_Stereo_Depth_Estimation_ICCV_2023_paper.html 概述 立体匹配模型难以处理无纹理场景的匹配&#xff0c;现有的方法通常假设物体表面是光滑的&#xff0c;或者光照是…

express中实现将mysql中的数据导出为excel

express中实现将mysql中的数据导出为excel 安装node-excel cnpm install node-xlsx -S封装公用的导出方法 /*** 查询* param tableName: 表名* param sqlJson&#xff1a;需要拼接的SQL* returns {Promise<unknown>}*/ const find (tableName, sqlJson) > {return…

Linux——权限

个人主页&#xff1a;日刷百题 系列专栏&#xff1a;〖C语言小游戏〗〖Linux〗〖数据结构〗 〖C语言〗 &#x1f30e;欢迎各位→点赞&#x1f44d;收藏⭐️留言&#x1f4dd; ​ ​ 一、 Linux下用户的分类 Linux下有两种用户&#xff1a; 1. root&#xff08;超级管理员用户…

基于FPGA的HDMI编码模块设计(包含工程源文件)

前文已经通过FPGA实现了TMDS视频编码的算法&#xff0c;也对单沿数据采样转双沿数据采样的ODDR原语做了详细讲解和仿真验证&#xff0c;本文将这些模块结合&#xff0c;设计出HDMI编码模块&#xff0c;在HDMI接口的显示器上显示一张图片。 1、整体思路 如图1所示&#xff0c;是…

Github 2023-12-18 开源项目周报 Top14

根据Github Trendings的统计&#xff0c;本周(2023-12-18统计)共有14个项目上榜。根据开发语言中项目的数量&#xff0c;汇总情况如下&#xff1a; 开发语言项目数量TypeScript项目4Python项目4Jupyter Notebook项目3非开发语言项目1JavaScript项目1Rust项目1Go项目1 基于项目…

【5G PHY】5G小区类型、小区组和小区节点的概念介绍

博主未授权任何人或组织机构转载博主任何原创文章&#xff0c;感谢各位对原创的支持&#xff01; 博主链接 本人就职于国际知名终端厂商&#xff0c;负责modem芯片研发。 在5G早期负责终端数据业务层、核心网相关的开发工作&#xff0c;目前牵头6G算力网络技术标准研究。 博客…

前后端传参中遇见的问题

前后端传参经常容易出错&#xff0c;本文记录开发springBootMybatis-plusvuecli项目中出现的传参问题及解决办法 1.前后端没有跨域配置&#xff0c;报错 解决方法&#xff1a;后端进行跨域配置&#xff0c;拷贝CorsConfig类 package com.example.xxxx.config;import org.spr…

web服务器之——基于虚拟目录和用户控制的web网站

目录 一、虚拟目录 虚拟目录的作用&#xff1a; 二、搭建基于虚拟目录的web网站 1、www服务器配置 2、搭建静态网站 设置防火墙状态 关闭文件访问权限——SeLinux 3、编辑网页资源文件 4、设置虚拟目录 5、向虚拟目录中写入资源 6、重启httpd 三、搭建基…

Flink系列之:监控反压

Flink系列之&#xff1a;监控反压 一、反压二、Task 性能指标三、示例四、反压状态 Flink Web 界面提供了一个选项卡来监控正在运行 jobs 的反压行为。 一、反压 如果你看到一个 task 发生 反压警告&#xff08;例如&#xff1a; High&#xff09;&#xff0c;意味着它生产数…

什么是缓存击穿、缓存穿透、缓存雪崩?

&#x1f680; 作者主页&#xff1a; 有来技术 &#x1f525; 开源项目&#xff1a; youlai-mall &#x1f343; vue3-element-admin &#x1f343; youlai-boot &#x1f33a; 仓库主页&#xff1a; Gitee &#x1f4ab; Github &#x1f4ab; GitCode &#x1f496; 欢迎点赞…

postman脚本生成可执行文件(6)

一.通过Python脚本&#xff08;executescript.py&#xff09;执行newman指令 #!usr/bin/python import subprocess from datetime import datetimeclass Newman_automate():Newman_automate():该类主要是定义postman脚本执行__path:cmd命令行中执行newnan脚本指令&#xff08;…

C语言—每日选择题—Day50

一天一天的更新&#xff0c;也是达到50天了&#xff0c;精选的题有250道&#xff0c;博主累计做了不下500道选择题&#xff0c;最喜欢的题型就是指针和数组之间的计算呀&#xff0c;不知道关注我的小伙伴是不是一直在坚持呢&#xff1f;文末有投票&#xff0c;大家可以投票让博…

[Big Bird]论文解读:Big Bird: Transformers for Longer Sequences

文章目录 1 介绍2 模型架构3 结果 论文&#xff1a;Big Bird: Transformers for Longer Sequences 作者&#xff1a;Manzil Zaheer, Guru Guruganesh, Avinava Dubey, Joshua Ainslie, Chris Alberti, Santiago Ontanon, Philip Pham, Anirudh Ravula, Qifan Wang, Li Yang, Am…

【数据结构】树状数组总结

知识概览 树状数组有两个作用&#xff1a; 快速求前缀和 时间复杂度O(log(n))修改某一个数 时间复杂度O(log(n)) 例题展示 1. 单点修改&#xff0c;区间查询 题目链接 活动 - AcWing本活动组织刷《算法竞赛进阶指南》&#xff0c;系统学习各种编程算法。主要面向…