堆的实现-向上调整算法-向下调整算法-堆排序-TopK问题 C语言

一、堆的概念及结构

二、 向上调整算法

注意:循环条件不可写parent > 0

//向上调整算法
//child为下标
void adjustup(int* a, int child)
{int 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;}}
}

 三、向下调整算法

他的时间复杂度比向上调整算法要更低,因此尽可能用向下调整算法

//向下调整算法
//n为数据个数,parent为下标
void adjustdown(int* a, int n, int parent)
{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;}}
}

四、完整的堆的实现

Heap.h 

#pragma once
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include<assert.h>
#include<stdbool.h>//小堆
typedef int HPDataType;
typedef struct Heap
{HPDataType* _a;int _size;int _capacity;
}Heap;void HeapInit(Heap* hp);
// 堆的销毁
void HeapDestory(Heap* hp);
// 堆的插入
void HeapPush(Heap* hp, HPDataType x);
// 堆的删除
void HeapPop(Heap* hp);
// 取堆顶的数据
HPDataType HeapTop(Heap* hp);
// 堆的数据个数
int HeapSize(Heap* hp);
// 堆的判空
bool HeapEmpty(Heap* hp);

heap.c

#include"Heap.h"void HeapInit(Heap* hp)
{assert(hp);hp->_a = NULL;hp->_capacity = 0;hp->_size = 0;
}
// 堆的销毁
void HeapDestory(Heap* hp)
{assert(hp);free(hp->_a);hp->_a = NULL;hp->_capacity = 0;hp->_size = 0;
}// 堆的判空
bool HeapEmpty(Heap* hp)
{assert(hp);return 0 == hp->_size;
}
void swap(HPDataType* p1, HPDataType* p2)
{int tmp = *p1;*p1 = *p2;*p2 = tmp;
}
//向上调整算法
//child为下标
void adjustup(HPDataType* a, int child)
{int 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;}}
}
//向下调整算法
//n为数据个数,parent为下标
void adjustdown(HPDataType* a, int n, int parent)
{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;}}
}
// 堆的插入
void HeapPush(Heap* hp, HPDataType x)
{assert(hp);if (hp->_capacity == hp->_size){int newcapacity = (hp->_capacity == 0 ? 4 : hp->_capacity * 2);HPDataType* tmp = (HPDataType*)realloc(hp->_a, sizeof(HPDataType) * newcapacity);if(NULL == tmp){perror("HeapPush realloc fail!!");return;}hp->_a = tmp;hp->_capacity = newcapacity;}hp->_a[hp->_size] = x;hp->_size++;adjustup(hp->_a, hp->_size - 1);
}
// 堆的删除,指删除顶部数据
void HeapPop(Heap* hp)
{assert(hp);assert(!HeapEmpty(hp));swap(&hp->_a[0], &hp->_a[hp->_size - 1]);hp->_size--;adjustdown(hp->_a, hp->_size, 0);}
// 取堆顶的数据
HPDataType HeapTop(Heap* hp)
{assert(hp);assert(!HeapEmpty(hp));return hp->_a[0];
}
// 堆的数据个数
int HeapSize(Heap* hp)
{assert(hp);return hp->_size;
}

heaptest.c 

#include"Heap.h"void test()
{Heap hpp;HeapInit(&hpp);int aa[] = { 65,100,70,32,50,60 };for (int i = 0; i < sizeof(aa) / sizeof(int); ++i){HeapPush(&hpp, aa[i]);}while(!HeapEmpty(&hpp)){int top = HeapTop(&hpp);printf("%d\n", top);HeapPop(&hpp);}HeapDestory(&hpp);
}
typedef int datatype;
//利用向上调整建堆
//n为元素个数
void CreatHeapByadjustup(datatype* a, int n)
{int i = 0;for (i = 1; i< n; i++){adjustup(a, i);}
}
//利用向下调整建堆
// 他的时间复杂度更低
//n为元素个数
void CreatHeapByadjustdown(datatype* a, int n)
{int i = 0;//叶子结点无法下调整,所以传入最后一个父亲//最后一个父亲等于元素个数(n - 1 - 1) / 2for (i = (n - 2) / 2; i >= 0; i--){adjustdown(a, n, i);}
}
//堆排序
//n为元素个数
void HeapSort(datatype* a, int n)
{//利用向下调整建堆CreatHeapByadjustdown(a, n);int end = n - 1;while (end){swap(&a[0], &a[end]);end--;//将数组第一个元素放到合适位置,重新变为堆adjustdown(a, end, 0);}
}
//int main()
//{
//	//test();
//	//利用向上调整建堆
// 	//int aa[] = { 65,100,70,32,50,60 };
//	//利用向上调整建堆
//	//CreatHeapByadjustup(aa, sizeof(aa) / sizeof(int));
//	//利用向下调整建堆
//	//CreatHeapByadjustdown(aa, sizeof(aa) / sizeof(int));
//	//堆排序,
//	//想要获得降序,就要建立小堆
//	//因为建立小堆可以取出最小的值放到数组尾部,然后再建小堆,
//	//同样想要获得降升序,就要建立大堆
//	//HeapSort(aa, sizeof(aa) / sizeof(int));
//
//	
//	return 0;
//}

 五、堆排序

        想要获得降序,就要建立小堆,因为建立小堆可以取出最小的值放到数组尾部,然后再建小堆,同样想要获得降升序,就要建立大堆

//利用向上调整建堆
//n为元素个数
void CreatHeapByadjustup(datatype* a, int n)
{int i = 0;for (i = 1; i< n; i++){adjustup(a, i);}
}
//利用向下调整建堆
// 他的时间度更低
//n为元素个数
void CreatHeapByadjustdown(datatype* a, int n)
{int i = 0;//叶子结点无法下调整,所以传入最后一个父亲//最后一个父亲等于元素个数(n - 1 - 1) / 2for (i = (n - 2) / 2; i >= 0; i--){adjustdown(a, n, i);}
}
//堆排序
//n为元素个数
void HeapSort(datatype* a, int n)
{//利用向下调整建堆CreatHeapByadjustdown(a, n);int end = n - 1;while (end){swap(&a[0], &a[end]);end--;//将数组第一个元素放到合适位置,重新变为堆adjustdown(a, end, 0);}
}
int main()
{test();//利用向上调整建堆int aa[] = { 65,100,70,32,50,60 };//利用向上调整建堆CreatHeapByadjustup(aa, sizeof(aa) / sizeof(int));//利用向下调整建堆CreatHeapByadjustdown(aa, sizeof(aa) / sizeof(int));//堆排序,//想要获得降序,就要建立小堆//因为建立小堆可以取出最小的值放到数组尾部,然后再建小堆,//同样想要获得降升序,就要建立大堆HeapSort(aa, sizeof(aa) / sizeof(int));return 0;
}

六、Top-K 问题

Top-k问题:
     假设有10万亿数据,取k个最大的.数据量很大,就不可以把数都存进去,因为存储空间不允许
    解决思路:

        那么我们就开辟K个空间的数组,插入K个数据建小堆, 然后再插入就和堆中最小数(数组第一个数)进行比较,堆中最小数比较小,就插入代替他,利用堆排序,重新将鼠标变为堆,当遍历完所有数据,数组中存放的就是最大的K个数字

注:adjustdown()函数在前面堆的实现有

/为了方便直接观察,我们可以创造数据
void CreateNDate()
{// 造数据int n = 10000;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);
}void PrintTopK(int k)
{const char* file = "data.txt";FILE* fout = fopen(file, "r");if (fout == NULL){perror("fopen error");return;}int* kminheap = (int*)malloc(sizeof(int) * k);if (kminheap == NULL){perror("malloc error");return;}//读取前k个数据for (int i = 0; i < k; i++){fscanf(fout, "%d", &kminheap[i]);}// 将10个数据建小堆for (int i = (k - 1 - 1) / 2; i >= 0; i--){adjustdown(kminheap, k, i);}//之后的插入int val = 0;while (!feof(fout)){fscanf(fout, "%d", &val);if (val > kminheap[0]){kminheap[0] = val;adjustdown(kminheap, k, 0);}}for (int i = 0; i < k; i++){printf("%d ", kminheap[i]);}printf("\n");
}
int main()
{//创造第一次之后,就注释,//然后打开文件手动将4个数改为最大的再次运行CreateNDate();PrintTopK(5);return 0;
}

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

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

相关文章

CoderGuide

CoderGuide是一个针对同学们前后端求职面试的开源项目&#xff0c;作为一名互联网/IT从业人员&#xff0c;经常需要搜索一些书籍、面试题等资源&#xff0c;在这个过程中踩过很多坑、浪费过很多时间。欢迎大家 Watch、Star&#xff0c;供各位同学免费使用&#xff0c;永不收费&…

Spring框架 配置Gateway网关/spring cloud gateway 基础入门案例教程

文章目录 目录 文章目录 安装流程 小结 概要安装流程技术细节小结 概要 网关作为微服务集群唯一的对外入口,可以实现很多功能. 例如: 统一的解决跨域(一个ajax请求 origin域名和请求目标url中域名不同,ip不同,域名不同,端口不同,都会引发的问题)问题. 统一的身份认证.认证解…

C++ 关键字与库函数 学习总结

sizeof与strlen 含义 sizeof&#xff1a;是一个操作符&#xff0c;用于计算数据类型或变量的大小&#xff08;以字节为单位&#xff09;。在编译时求值strlen&#xff1a; 是一个函数&#xff0c;用于计算字符串的长度&#xff08;不包括终止符 \0&#xff09;。在运行时求值不…

考研数学|保100冲130暑假强化保姆级规划

只做这些的话还不够&#xff0c;还要加上真题、模拟题。而且必须确保自己完全掌握上面的内容。 只看30讲和做1000题考90分是比较有困难的。如果刷完知能行1000题&#xff0c;90分应该很稳。 张宇1000题是考研数学难度较大一些的题集&#xff0c;题目难&#xff0c;计算量大&a…

机器学习笔记 - RAFT 光流简读

一、光流 光流是图像序列中像素的表观运动。为了估计光流,场景中物体的移动必须具有相应的亮度位移。这意味着一个图像中移动的红球在下一个图像中应该具有相同的亮度和颜色,这使我们能够确定它以像素为单位移动了多少。下图显示了光流示例,其中一系列图像捕获了逆时针旋转的…

增加一个按钮,批量获取凭证号

create PROCEDURE Cux_Ar_ServiceLedger_Voucher_ProcOrgId Int ,result Int output AS BEGIN SET NOCOUNT ONDECLARE Date DATETIME IF OrgId 0 or OrgIdBEGIN RAISERROR(N获取当前组织ID失败&#xff01;, 16, 1) RETURNEND SET Date GETDATE()BEGIN TRANSACTION BEGIN…

微调(一)

微调有两种办法&#xff0c; 一是模型全部参数的微调&#xff0c;二是少量参数高效的微调。前者由于参数多&#xff0c;需要的GPU多&#xff0c;并且全参数微调可能把模型带偏&#xff0c;后者只需要微调少量参数&#xff0c;需要的GPU少&#xff0c;还可能达到不错的效果&…

秒懂Linux之自动化构建工具-make/Makefile

目录 一.前文摘要 二.make/Makefile 一.前文摘要 在学习自动化构建工具前我们先来补充一下动静态库的相关指令 动态库指令 gcc -o 文件&#xff08;重命名&#xff09; 源文件 静态库指令 gcc -o 文件&#xff08;重命名&#xff09; 源文件 -static 二.make/Makefile 怎么形…

MATLAB(14)预处理

一、前言 在MATLAB中进行插值拟合、主成分分析&#xff08;PCA&#xff09;和小波分析之前&#xff0c;通常需要对数据进行一些预处理。这些预处理步骤可能包括数据清洗、缺失值处理、标准化或归一化等。下面我将分别为这三种分析方法提供预处理模型的示例代码。 二、实现 1.…

校园点餐系统

1 项目介绍 1.1 摘要 在这个被海量信息淹没的数字化时代&#xff0c;互联网技术以惊人的速度迭代&#xff0c;信息的触角无处不在&#xff0c;社会的脉动随之加速。每一天&#xff0c;我们都被汹涌而至的数据浪潮包裹&#xff0c;生活在一个全方位的数字信息矩阵中。互联网的…

大模型微调实战项目总结(非常详细)零基础入门到精通,收藏这一篇就够了

写在前面 不知不觉之间&#xff0c;距开源ChatGLM-Finetuning项目已经过去了8个月。大模型也在飞速的发展&#xff0c;开源社区也是越来越活跃&#xff0c;开源模型越来越多。 中间更新过一次&#xff0c;将代码重构让大家更容易理解&#xff0c;本次更新主要增加ChatGLM3模型…

JavaScript (十)——JavaScript 比较 和 逻辑运算符

目录 JavaScript 比较 和 逻辑运算符 比较运算符 如何使用 逻辑运算符 条件运算符 语法 JavaScript 比较 和 逻辑运算符 比较和逻辑运算符用于测试 true 或者 false 比较运算符 比较运算符在逻辑语句中使用&#xff0c;以测定变量或值是否相等。 如何使用 可以在条件语…

【C++】模拟实现list

&#x1f984;个人主页:修修修也 &#x1f38f;所属专栏:数据结构 ⚙️操作环境:Visual Studio 2022 目录 一.了解项目及其功能 &#x1f4cc;了解list官方标准 了解模拟实现list &#x1f4cc;了解更底层的list实现 二.list迭代器和vector迭代器的异同 &#x1f4cc;迭代…

tomcat配置(java环境配置)

继昨天上线商城系统 [rootstaticserver eleme_web]# cd /usr/local/nginx/conf [rootstaticserver conf]# ls fastcgi.conf koi-utf nginx.conf scgi_params.default fastcgi.conf.default koi-win nginx.conf.bak uwsgi…

采用GDAL批量波段运算计算植被指数0基础教程

采用GDAL批量波段运算计算植被指数0基础教程 1. 引言 在传统的遥感数据处理方法中&#xff0c;通常使用ArcGis或ENVI软件进行波段运算。然而&#xff0c;这些软件在处理大量数据时往往效率低下。有没有一种方法可以批量进行波段运算&#xff0c;一下子计算几十个植被指数&…

计算word文件打印页数 VBA实现

目录 场景复现环境说明实现原理计算当前文件夹下所有word文件页数总和利用递归计算当前文件夹所有work文件页面数量几个BUG计算结果软件报价后话 场景复现 最近需要帮我弟打印高考资料&#xff0c;搜集完资料去网上打印&#xff0c;商家发出了这个计算页数的界面。我就好奇怎么…

如何把视频语音转文字?交给这4款工具就完事

这两天巴黎奥运会的盛大开幕&#xff0c;世界各地的记者们纷纷涌入这个体育盛事的现场&#xff0c;带着他们的镜头和麦克风&#xff0c;捕捉每一个激动人心的瞬间。 然而&#xff0c;随着采访的深入&#xff0c;如何快速准确地将这些珍贵的视频内容转化为文字记录&#xff0c;…

C语言 | Leetcode C语言题解之第309题买卖股票的最佳时机含冷冻期

题目&#xff1a; 题解&#xff1a; int maxProfit(int* prices, int pricesSize) {if (pricesSize 0) {return 0;}int f0 -prices[0];int f1 0;int f2 0;for (int i 1; i < pricesSize; i) {int newf0 fmax(f0, f2 - prices[i]);int newf1 f0 prices[i];int newf2…

Linux 和 Unix 的关系

Linux 和 Unix 的关系 2.2.1unix 是怎么来的 2.2.2Linux 是怎么来的 GNU计划的另一个目的是构建自由的软件文化&#xff0c;以支持以无条件自由软件和开放源码程序这种文化理念为核心的一整套系统&#xff0c;来推动软件在世界范围内的普及及发展。其中包括支持点&#xff08;推…

海思Hi35XX系列(一)环境搭建与挂载

小白一个&#xff0c;新的开发板刚到手有点懵&#xff0c;之前没弄过没有经验&#xff0c;简单记录一下吧 一般买开发板都会给带一个已经配置好的虚拟机文件&#xff0c;直接使用就可以 一、下载安装虚拟机与镜像文件 VMware-workstation16.1.0 我的镜像文件是官方文档资料…