数据结构--堆排序(超详细!)

一、前言

堆排序与Top K问题是堆的两大应用,在我们日常也有很广泛的用处

我们已经上面已经说过了堆,这次来说堆的其中一个应用---堆排序。
 

二、堆排序

堆排序优势在哪里?有什么恐怖之处吗?

重点:拿一个举例:我们上一篇博客在代码运用过程中,我们的HeapPop函数每次删除堆顶元素之后进行向下调整之后,都能找到次大或者次小的值。

int main()
{HP php;InitHeap(&php);int a[] = { 4,7,2,3,9,5,1 };for (int i = 0; i < sizeof(a) / sizeof(a[0]); i++)//建堆{PushHeap(&php, a[i]);}while (!HeapEmpty(&php))//进入循环,直至堆为空{printf("%d ", HeapTop(&php));//打印堆顶元素HeapPop(&php);//删除堆顶元素}DestroyHeap(&php);return 0;
}

  这样就把我们所想要的排序好了,我们每取出一个次大或者次小的值,时间复杂度都是O(log N),当有1000个数据时,各个元素比较查找那就需要进行1000次,而我们这种做法10次就够了。效率很高。分析上面代码,还是有点缺陷的,在我们建堆的时候,我们是从源头数组里面取数据,再新开辟空间建堆,源头数组并没有变化,这便造成了空间的浪费。所以,有没有一种高效又节省空间的方法呢----堆排序。

  我们要想节省空间,最好需要做到不另开辟空间,我们已经定义了一个数组,并且想将数组里面的元素进行排序,那为什么我们不在原数组上找路子呢?

1、建堆

 开辟空间的建堆方式,先将源头数组里面的元素放入我们开辟的结构体中的数组里,再进行向上调整建堆。那为何我们不直接将源头数组元素直接进行向上调整呢?

我们可以直接将原数组传给AdjustUp函数,再先将数组中第一个元素进行向上调整,接着再第二个元素,这样依次进行向上调整。

int a[] = { 4,7,2,3,9,5,1,6,8};int n = sizeof(a) / sizeof(a[0]);int i = 0;for (i = 1; i < n; i++){AdjustUp(&a, i);}

我们打印一下看看结果:

因为我们上述向上调整函数最终调整为小堆,这里就拿小堆来做参考:

监视查看数组的变化:

  可以看到,数组中元素已经是小堆。这样既满足了我们的建堆要求,也降低了空间的消耗

2、排序

  那么,话说回来,堆是随便建的吗?直接建一个大堆或者小堆都可以满足我们要求吗?有没有什么要求呢?

  我们在开头举国一个例子:我们的HeapPop函数每次删除堆顶元素之后进行向下调整之后,都能找到次大或者次小的值。

  HeapPop函数的逻辑是,将堆顶元素A与堆尾元素B互换,然后A删除,将B向下调整建堆。

  如果刚开始建的是小堆,我们交换堆顶元素A和队尾元素B后不着急删除A,既然是小堆,那么A肯定是所有元素中的最小值,交换后在队尾。我们再进行向下调整后,重建建小堆(这里重新建堆时不要将A也加入建堆的操作中,因为我们没有删除A),这时候的堆顶元素就是次小的值。我们将堆顶元素再与倒数第二个元素进行交换,这样次小的值就在倒数第二个位置了,再进行向下调整。这两个操作多次进行,直到剩下最后一个元素。我们每次都是找次小的值将它放在数组中最后一个,这样下来,我们最终就会得到排序好的元素,为降序

  如果是大堆呢?每次向下调整都会找到次大的值,堆顶元素与堆尾元素交换后,次大的值依次从后向前排列,最后我们便得到排序好的元素,为升序。

 

所以我们可以总结出,升序建大堆,降序建小堆。

代码如下(以降序举例):

int main()
{int a[] = { 4,7,2,3,9,5,1,6,8};int n = sizeof(a) / sizeof(a[0]);int i = 0;//在数组里建堆,减少了空间消耗//升序建大堆,降序建小堆 for (i = 1; i < n; i++){AdjustUp(&a, i);}//查看建堆后的元素排列for (i = 0; i < n; i++){printf("%d ", a[i]);}printf("\n");//重新定义一个变量,将元素大小赋值给它.不改变nint end = n - 1;while(end > 0){Swap_HP(&a[0],&a[end]);//交换堆顶元素与堆尾元素AdjustDown(&a,end, 0);//向下调整找到此小值end--;//在下一次交换中,让新的堆顶元素与新的堆尾元素交换。}for (i = 0; i < n; i++){	printf("%d ", a[i]);}return 0;
}

这一趟下来时间复杂度只有N*logN,比最开始学的冒泡排序快了不少。数据越多,就越能体现出堆排序的优越性!

以上就是堆排序要说的所有内容。

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

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

相关文章

Java项目要不要部署在Docker里?

部署Java项目有很多种方式&#xff0c;传统的方式是直接在物理机或虚拟机上部署应用&#xff0c;但为什么现在容器化部署变得越来越流行&#xff0c; 个人觉得原因有以下几个&#xff1a; 1、 环境一致性&#xff1a;使用Docker可以确保开发、测试和生产环境的一致性&#xff…

使用libtorch实现sobel算子进行边缘检测,python和c++实现

文章目录 pythonpython结果 cppc结果 python import torch import torch.nn as nn from PIL import Image import numpy as np import cv2class SobelEdgeDetector(nn.Module):def __init__(self):super(SobelEdgeDetector, self).__init__()self.convx nn.Conv2d(1,1,3,padd…

植物病害检测YOLOV8,OPENCV调用

【免费】植物病害检测&#xff0c;10种类型&#xff0c;YOLOV8训练&#xff0c;转换成ONNX&#xff0c;OPENCV调用资源-CSDN文库 植物病害检测&#xff0c;YOLOV8NANO&#xff0c;训练得到PT模型&#xff0c;然后转换成ONNX&#xff0c;OPENCV的DNN调用&#xff0c;支持C,PYTH…

实现vue3响应式系统核心-shallowReactive

简介 今天来实现一下 shallowReactive 这个 API。 reactive函数是一个深响应&#xff0c;当你取出的值为对象类型&#xff0c;需要再次调用 reactive进行响应式处理。很明显我们目前的代码是一个浅响应&#xff0c;即 只代理了对象的第一层&#xff0c;也就是 shallowReactiv…

【java核心-IoC(控制反转)和DI(依赖注入)及AOP(面向切面编程)】

java核心-IoC&#xff08;控制反转&#xff09;和DI&#xff08;依赖注入&#xff09;及AOP&#xff08;面向切面编程&#xff09; 控制反转&#xff08;IoC&#xff09;依赖注入&#xff08;DI&#xff09;面向切面编程&#xff08;AOPAOP的应用场景包括但不限于&#xff1a;以…

安装和启动berTopic,hdbscan和importlib.metadata

1. 安装问题&#xff1a;hdbsacn 安装berTopic的时候&#xff0c;包 hdbsacn一直安装失败&#xff0c;报出以下错误&#xff1a; 尝试了很多办法&#xff1a;① 下载hdbscan的tar.gz文件安装&#xff0c;安装失败&#xff1b;② 安装*.whl文件&#xff0c;安装成功&#xff…

【C++初阶】C++入门(2)

&#x1f525;博客主页&#xff1a; 小羊失眠啦. &#x1f3a5;系列专栏&#xff1a;《C语言》 《数据结构》 《C》 《Linux》 《Cpolar》 ❤️感谢大家点赞&#x1f44d;收藏⭐评论✍️ 文章目录 一、函数重载1.1 函数重载的概念1.2 函数重载的种类1.3 C支持函数重载的原理 二…

海外短剧系统国际短剧源码h5多语言版app挂载tiktok油管ins

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目 前言 一、海外短剧系统是什么&#xff1f; 二、海外短剧系统功能与运营方式介绍 1.系统功能 2.短剧APP运营方式 总结 前言 本文简单介绍海外短剧系统的功能&#xff…

Flutter的安装与环境配置

一、下载安装Futter&#xff1a; 1、Flutter中文文档&#xff1a; 安装和环境配置 - Flutter 中文文档 - Flutter 中文开发者网站 - Flutter 2、下载 Futter SDK&#xff1a; Flutter中文文档 里面有&#xff0c;下载完成之后找个文件夹解压出来&#xff0c;最好不要将 Flu…

asp.net core监听本地ip地址

开发asp.net core的时候遇到一个问题我想提供访问供其他同事测试&#xff0c;但是默认都是localhost或者127.0.0.1。我想换成我的Ip地址访问但是不行&#xff0c;百度搜索需要更换监听的地址即修改launchSettings.json&#xff0c;修改为0.0.0.0:5248&#xff0c;这样不管local…

Enlight官方第三届“金融帝国杯”玩家游戏视频邀请赛《获奖者名单公布》

Enlight官方第三届“金融帝国杯”玩家游戏视频邀请赛 《获奖者名单公布》 ————————————— Ⅰ〖公布单位〗 金融之路CapLab官方中文社群竞赛委员会 ————————————— Ⅱ〖公布时间〗 2024年01月31日 ————————————— Ⅲ〖获奖结果〗 一等奖1名…

gdp调试—Linux

目录 介绍 使用 介绍 代码分为debug模式和release模式 如果一份代码要被调试&#xff0c;这份代码必须是debug Linux下编译代码默认是是release模式 如果你想代码是debug模式 必须加上 - g 小提&#xff1a; vim默认&#xff1a;命令模式 gcc默认&#xff1a;releas…