详细堆排序的实现

news/2025/2/13 5:53:10/

目录

建堆有两种方法(以升序为例):

建完堆之后,就可以去排序了:

以下是向上调整和向下调整的两个接口:

完整实现和测试代码:

首先,排序之前要先建立一个堆来实现排序

由于兄弟之间无大小关系,所以:

        实现升序要创建大堆

        实现降序要创建小堆

建堆有两种方法(以升序为例):

1.利用AdjustUp(向上调整):

从第二个数据(因为第一个数据上面无父节点),也就是下标为1的那个点开始遍历调整数据,只要该节点上面的父节点比该点小,就互换数据(Swap),最后就会建立出一个大堆。

    // 建大堆// O(N*logN)for (int i = 1; i < n; i++){AdjustUp(a, i);}

2.利用AdjustDown(向下调整):

从倒数第一个非叶子节点,也就是倒数第一个父节点开始(建成分成许多个分散的大堆),只要该节点上面的父节点比该点小,就互换数据(Swap),最后就会建立出一个大堆。

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

这两种方法中,更推荐下面这种,因为时间复杂度稍低,而且下方排序也要用到向下调整接口,这样就节省了一个接口。

建完堆之后,就可以去排序了:

通过大堆的顶端元素最大的特性,可以将尾数据和top数据交换(Swap),AdjustDown的参数中传进去的end是个判断点,size--后,就可以将top那个最大的数据保存在尾部,然后利用向上调整的特性,次大的数据又到了top点,再次交换,size--,依次进行下去,最后就将最大,次大,次次大......依次放到了尾部,就排序完成了。

	//0(N*logN)int end = n - 1;while (end > 0){Swap(&a[0], &a[end]);AdjustDown(a, end, 0);end--;}

以下是向上调整和向下调整的两个接口:

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;}}
}void AdjustDown(int* a, int size, int parent)
{int child = parent * 2 + 1;while (child < size){// 假设左孩子大if (child + 1 < size && a[child + 1] > a[child]){++child;}if (a[child] > a[parent]){Swap(&a[child], &a[parent]);parent = child;child = parent * 2 + 1;}else{break;}}
}

完整实现和测试代码:

#include<stdio.h>
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<stdbool.h>typedef int HPDataType;void Swap(HPDataType* p1, HPDataType* p2)
{HPDataType tmp = *p1;*p1 = *p2;*p2 = tmp;
}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;}}
}void AdjustDown(int* a, int size, int parent)
{int child = parent * 2 + 1;while (child < size){// 假设左孩子大if (child + 1 < size && 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 HeapSort(int* a, int n)
{// 建大堆// O(N*logN)/*for (int i = 1; i < n; i++){AdjustUp(a, i);}*/// O(N)for (int i = (n - 1 - 1) / 2; i >= 0; --i){AdjustDown(a, n, i);}//0(N*logN)int end = n - 1;while (end > 0){Swap(&a[0], &a[end]);AdjustDown(a, end, 0);end--;}
}int main()
{int a[] = { 4, 6, 2, 1, 5, 8, 2, 9 };HeapSort(a, sizeof(a)/sizeof(int));for (int i = 0; i < sizeof(a)/sizeof(int); i++){printf("%d ", a[i]);}printf("\n");return 0;
}

http://www.ppmy.cn/news/1245339.html

相关文章

【华为OD】统一考试B\C卷真题 100%通过:开源项目热榜 C/C++实现

目录 题目描述&#xff1a; 示例1 示例2 题目描述&#xff1a; 某个开源社区希望将最近热度比较高的开源项目出一个榜单&#xff0c;推荐给社区里面的开发者。对于每个开源项目&#xff0c;开发者可以进行关注(watch)、收藏(star)、fork、提issue、提交合并请求(MR)等。 数…

Flink 替换 Logstash 解决日志收集丢失问题

在某客户日志数据迁移到火山引擎使用 ELK 生态的案例中&#xff0c;由于客户反馈之前 Logstash 经常发生数据丢失和收集性能较差的使用痛点&#xff0c;我们尝试使用 Flink 替代了传统的 Logstash 来作为日志数据解析、转换以及写入 ElasticSearch 的组件&#xff0c;得到了该客…

[计算机网络]运输层概述

虽然我自己也不知道写在前面和前言有什么区别..... 这个系列其实是针对<深入浅出计算机网络>的简单总结,加入了一点个人的理解和浅薄见识,如果您有一些更好的意见和见解,欢迎随时协助我改正,感激不尽啦. 最近心态平和了不少, 和过去也完全做了个割舍吧,既然痛苦和压力的…

Windows系统 TexWorks 显示“Font Monaco not found.“

先双击MONACO.ttf文件完成安装&#xff0c;还是不行用以下方法解决&#xff1a; 解决方法&#xff1a;将Monaco.ttf后缀&#xff08;不一定非要这个格式的&#xff0c;可以自行尝试&#xff09;的字体文件解压&#xff0c;复制进texlive文件夹下的路径,例如&#xff1a; C:\t…

技术阅读周刊第第7️⃣期

技术阅读周刊&#xff0c;每周更新。 历史更新 20231013&#xff1a;第一期20231022&#xff1a;第二期20231027&#xff1a;第三期20231103&#xff1a;第四期20231107&#xff1a;第五期20231117&#xff1a;第六期 What is a JWT? Understanding JSON Web Tokens URL: http…

1140. 最短网络,prim算法,模板题

1140. 最短网络 - AcWing题库 农夫约翰被选为他们镇的镇长&#xff01; 他其中一个竞选承诺就是在镇上建立起互联网&#xff0c;并连接到所有的农场。 约翰已经给他的农场安排了一条高速的网络线路&#xff0c;他想把这条线路共享给其他农场。 约翰的农场的编号是1&#xf…

女公务员脱机玩转Python,怎么做到的?

更多高级的Python技术文章请关注微信公众号&#xff1a;愤怒的it男 一、写在前面的故事 今天我发现了一件很神奇的事情&#xff1a;一位很漂亮的美女公务员&#xff0c;坐在一台没有外网的电脑面前&#xff0c;优雅地敲着Python代码&#xff0c;而这台电脑装的还是32位win7这种…

Linux学习笔记6-串口应用

到现在为止都是在开发板上运行的裸机程序&#xff0c;相当于之前学习STM32单片机时走过的路&#xff0c;还没有真正进入到核心的驱动开发部分&#xff0c;但这都是基础&#xff0c;所以慢慢来不着急。 接下来进入串口通信的学习&#xff0c;和GPIO一样&#xff0c;也是和单片机…