【数据结构与算法】堆排序算法原理与实现:基于堆实现的高效排序算法

   

            💓 博客主页:倔强的石头的CSDN主页 

           📝Gitee主页:倔强的石头的gitee主页

            ⏩ 文章专栏:《数据结构与算法》

                                  期待您的关注

 

1b7335aca73b41609b7f05d1d366f476.gif

 

目录

一、引言

堆排序的简介

堆排序的特点

二、堆的概念

三、堆排序算法的原理

四、堆排序的步骤

🍃构建堆 

🍃交换与调整

🍃重复过程

五、堆排序的性能分析

🍃时间复杂度:

🍃空间复杂度:

六、示例代码

七、总结


 

一、引言

堆排序的简介

堆排序(Heap Sort)是一种基于堆数据结构实现的排序算法。利用堆这种数据结构的高效性,通过构建和调整堆来实现排序,是一种性能优秀的排序算法。

堆排序的特点

  1. 时间复杂度:堆排序的最坏、最好、平均时间复杂度均为O(nlogn),其中n是待排序元素的数量。
  2. 稳定性:堆排序在排序过程中相等的元素不会交换位置,因此它是稳定的排序算法。
  3. 选择排序:堆排序是一种选择排序,它总是选择当前未排序部分的最大(或最小)元素进行排序。

 

二、堆的概念

关于堆的详细介绍,参考前置文章

【数据结构与算法】探索数组在堆数据结构中的妙用:从原理到实现-CSDN博客

 

三、堆排序算法的原理

  • 堆排序的基本思想是将待排序的序列构建成一个堆,然后依次将堆顶元素与堆尾元素交换,并将堆的大小减小1,再对剩余的堆进行调整,使其满足堆的性质。
  • 重复这个过程,直到堆的大小为1,此时排序完成。 

四、堆排序的步骤

🍃构建堆 

借助建堆算法,降序建小堆,升序建大堆,可以选择向上或者向下调整算法

向上调整建堆的原理:
模仿堆的插入操作来构建堆,从第一个子结点开始,将它看做是新插入的元素,向上调整至满足堆的性质,然后依次往后走,直到最后一个叶子节点完成上述调整

向下调整建堆的原理:
从最后一个父结点开始,先保证它和左右子树成为堆,然后依次往前走,保证每个父结点与左右子树成堆,直到最后根结点与左右子树成堆

 

关于建堆的向上调整算法和向下调整算法有时间复杂度推导

限于篇幅,这里就不展开推导了,直接给出结论

  • 向下调整建堆的时间复杂度为O(N)
  • 向上调整算法的时间复杂度为O(n*logN)

向下调整算法优于向上调整,所以应该选择向下调整算法

 这里分别给出向下调整建小堆和向下调整建大堆的算法

(如果关于向上调整算法和向下调整算法有疑惑,建议了解完堆的这篇文章之后再来看

【数据结构与算法】探索数组在堆数据结构中的妙用:从原理到实现-CSDN博客)

void Adjustdownsmall(DataType* a, int parent, int size)//向下调整建小堆算法
{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;}elsebreak;}
}
void Adjustdownbig(DataType* a, int parent, int size)//向下调整建大堆算法
{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;}elsebreak;}
}


 

🍃交换与调整

建堆之后,就是排序
以降序为例,每次将堆顶与堆尾数据交换(相当于将当前的最小值挪到最后),然后堆尾数据伪删除(有效数据个数--,不是真删除)进行一轮向下调整,恢复堆的结构

 

Swap(&a[0], &a[end]);//交换堆顶和堆尾数据
end--;
Adjustdownsmall(a, 0, end);//向下调整恢复堆的结构

 9b7e5cb844404312a312e019bae3b8bd.png

 

🍃重复过程

 重复上述交换与调整的过程,直到堆的大小为1,此时排序完成。

 

五、堆排序的性能分析

🍃时间复杂度:

  1. 建堆:对于长度为n的数组,建堆的时间复杂度为O(n)。这是因为建堆的过程中,元素需要逐个从数组尾部加入到堆中,并重新调整堆的结构以维持其性质。每个元素加入堆中最多会触发从该元素到根节点的路径上元素的重新调整,因此,平均而言,每个元素会触发O(log n)次调整。所以,建堆的总时间复杂度为O(n *log n)。但是,由于建堆的过程是线性的(从最后一个非叶子节点开始,逐个向上调整),所以实际的时间复杂度为O(n)。
  2. 排序:在排序阶段,每次从堆顶取出最大(或最小)元素,并重新调整堆结构的时间复杂度为O(log n)。因为需要排序n个元素,所以排序阶段的时间复杂度为O(n *log n)。

综上,堆排序的总时间复杂度为O(n) + O(n *log n) = O(n *log n)。

 

🍃空间复杂度:

堆排序的空间复杂度为O(1)。这是因为堆排序是原地排序算法,它只需要常数个额外的空间来存储临时变量,而不需要额外的存储空间来存储待排序的数组。所有的操作都是直接在原数组上进行的。所以,堆排序的空间复杂度非常低。

六、示例代码

(分别给出了完整的降序排序算法和升序排序算法)

#include<stdio.h>
#include<stdlib.h>#if 1
//堆排序
typedef int DataType;
void Swap(DataType* a, DataType* b)
{DataType tmp = *a;*a = *b;*b = tmp;
}
void Adjustdownsmall(DataType* a, int parent, int size)//向下调整建小堆算法
{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;}elsebreak;}
}
void Adjustdownbig(DataType* a, int parent, int size)//向下调整建大堆算法
{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;}elsebreak;}
}void HeapSortDOrder(DataType* a,int size)//降序排序
{//向下调整建小堆for (int i = (size - 2) / 2; i >= 0; i--)//从最后一个父节点调整{Adjustdownsmall(a, i, size);}int end = size - 1;while (end>0){Swap(&a[0], &a[end]);//交换堆顶和堆尾数据end--;Adjustdownsmall(a, 0, end);//向下调整恢复堆的结构}
}
void HeapSortAOrder(DataType* a, int size)//升序排序
{//向下调整建大堆for (int i = (size - 2) / 2; i >= 0; i--)//从最后一个父节点调整{Adjustdownbig(a, i, size);}int end = size - 1;while (end > 0){Swap(&a[0], &a[end]);//交换堆顶和堆尾数据end--;Adjustdownbig(a, 0, end);//向下调整恢复堆的结构}
}
#endifvoid print(DataType* a, int size)
{for (int i = 0; i < size; i++){printf("%d ", a[i]);}printf("\n");
}
int main()
{int arr[] = { 12,3,5,78,46,15,23,19,20,36,52 };int size = sizeof(arr) / sizeof(arr[0]);HeapSortDOrder(arr, size);//降序print(arr, size);HeapSortAOrder(arr, size);//升序print(arr, size);}

 27c88bb4be3d4b43beb24363a0fd02ae.png

七、总结

堆排序算法是一种高效且实用的排序算法,它通过利用堆数据结构的特点和性质,实现了对数据的高效排序。在实际应用中,我们可以根据问题的特点选择使用堆排序算法,以提高程序的性能和效率。

 

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

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

相关文章

15kg级弹簧刀高速巡飞无人机技术详解

弹簧刀高速巡飞无人机&#xff0c;作为一种先进的战术导弹系统&#xff0c;融合了无人机与导弹的双重特性&#xff0c;成为了现代战争中不可或缺的侦察与打击利器。该无人机以其小巧的外形设计、优异的性能表现和广泛的适用领域&#xff0c;受到了全球军事领域的广泛关注。弹簧…

【吊打面试官系列-MyBatis面试题】Mybatis 是如何进行分页的?分页插件的原理是什么?

大家好&#xff0c;我是锋哥。今天分享关于 【Mybatis 是如何进行分页的&#xff1f;分页插件的原理是什么&#xff1f;】面试题&#xff0c;希望对大家有帮助&#xff1b; Mybatis 是如何进行分页的&#xff1f;分页插件的原理是什么&#xff1f; Mybatis 使用 RowBounds 对象…

怎么测试远程服务器能否连通

远程服务器连接测试的方法很多&#xff0c;下面简单介绍下其中两种方法。 ping命令 按WINR快截键&#xff0c;打开“运行”对话框&#xff0c;输入cmd&#xff0c;回车&#xff0c;打开命令提示符。 输入ping IP地址或ping 域名即可&#xff0c;如ping360服务器通不通&#xf…

32 lambda表达式

c11 c98例子 在c98中&#xff0c;如果想要对一个数据集合中的元素进行排序&#xff0c;可以适用std::sort方法 #include <algorithm>#include <functional>int main(){int array[] {4,1,8,5,3,7,0,9,2,6};// 默认按照小于比较&#xff0c;排出来结果是升序 std…

Django + Vue 实现图片上传功能的全流程配置与详细操作指南

文章目录 前言图片上传步骤1. urls 配置2. settings 配置3. models 配置4. 安装Pillow 前言 在现代Web应用中&#xff0c;图片上传是一个常见且重要的功能。Django作为强大的Python Web框架&#xff0c;结合Vue.js这样的现代前端框架&#xff0c;能够高效地实现这一功能。本文将…

【Arduino】小飞鱼通达二开实验ESP32使用红外寻迹传感器 (图文)

在智能小车项目中都会有一个功能就是自动巡线&#xff0c;今天小飞鱼通达来实验的就是这个红外寻迹传感器。 红外寻迹传感器的原理就是有一个小灯发出红外光&#xff0c;光线照到物体后进行反射&#xff0c;有一个接收器进行接收&#xff0c;当在一定距离内会导通电路&#xf…

网安加·百家讲坛 | 肖文棣:铸盾护企——面对勒索病毒产业链的企业防护之道

作者简介&#xff1a;肖文棣&#xff0c;OWASP中国广东分会负责人、网安加社区特聘专家&#xff0c;现任某外企安全架构师&#xff0c;负责应用安全设计、管理和评审等工作。 引言 随着信息技术的飞速发展&#xff0c;网络安全问题愈发凸显&#xff0c;企业面临的网络安全威胁…

瞎谈指令集和寄存器读写来驱动硬件

文章目录 前言一、到底什么是指令集&#xff1f;二、为什么现代CPU需要指令集&#xff1f;三、开发完指令集究竟有什么缺点&#xff1f;四、寄存器读写怎么验证&#xff1f;总结 前言 其实很早以前就想对这个话题展开来聊聊&#xff0c;但是对体系结构的理解也仅仅限于《量化体…

应急响应:应急响应流程,常见应急事件及处置思路

「作者简介」&#xff1a;冬奥会网络安全中国代表队&#xff0c;CSDN Top100&#xff0c;就职奇安信多年&#xff0c;以实战工作为基础著作 《网络安全自学教程》&#xff0c;适合基础薄弱的同学系统化的学习网络安全&#xff0c;用最短的时间掌握最核心的技术。 这一章节我们需…

交通气象站:保障道路畅通的守护者

随着现代社会的飞速发展&#xff0c;交通网络日益密集&#xff0c;人们的出行越来越依赖于公路、铁路和航空等交通方式。然而&#xff0c;多变的天气条件常常给交通安全带来隐患&#xff0c;如大雾、雨雪、强风等恶劣天气不仅影响行车视线&#xff0c;还可能造成路面湿滑、结冰…

第十四届蓝桥杯省赛C++B组D题【飞机降落】题解(AC)

解题思路 这道题目要求我们判断给定的飞机是否都能在它们的油料耗尽之前降落。为了寻找是否存在合法的降落序列&#xff0c;我们可以使用深度优先搜索&#xff08;DFS&#xff09;的方法&#xff0c;尝试所有可能的降落顺序。 首先&#xff0c;我们需要理解题目中的条件。每架…

【MotionCap】pycharm 远程在wsl2 ubuntu20.04中root的miniconda3环境

pycharm wsl2 链接到pycharmsbin 都能看到内容,/root 下内容赋予了zhangbin 所有,pycharm还是看不到/root 下内容。sudo 安装了miniconda3 引发了这些问题 由于是在 root 用户安装的miniconda3 所以安装路径在/root/miniconda3 里 这导致了环境也是root用户的,会触发告警 WA…

冲击试样缺口拉刀V2U2U3U5

拉刀性能介绍 冲击试样缺口拉刀采用进口高速工具钢W18Cr4V材质&#xff0c;特殊工艺精密加工制造&#xff0c;硬度高&#xff0c;耐磨性好&#xff0c;使用寿命长&#xff0c;每把拉刀可加工试样达20&#xff0c;000多个。拉刀共54个齿&#xff08;深度5mm缺口拉刀为74个齿&am…

抖音本地生活服务商条件太高怎么办?低门槛方法来了!

随着本地生活赛道的潜力不断显现&#xff0c;本地生活服务商的数量也在与日俱增。而在所有开通本地生活服务板块的互联网平台中&#xff0c;日活跃用户数约8亿的抖音往往是众多创业者优先考虑的对象&#xff0c;以抖音本地生活服务商如何申请为代表的相关问题也因此常出现在多个…

排序算法(1)之插入排序----直接插入排序和希尔排序

个人主页&#xff1a;C忠实粉丝 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 C忠实粉丝 原创 排序之插入排序----直接插入排序和希尔排序(1) 收录于专栏【数据结构初阶】 本专栏旨在分享学习数据结构学习的一点学习笔记&#xff0c;欢迎大家在评论区交流讨…

页面加载503 Service Temporarily Unavailable异常

最近发现网页刷新经常503&#xff0c;加载卡主&#xff0c;刷新页面就正常了。 研究之后发现是页面需要的js文件等加载失败了。 再研究之后发现是nginx配置的问题。 我之前为了解决一个漏洞检测到目标主机可能存在缓慢的HTTP拒绝服务攻击 把nginx的连接设置了很多限制&#…

PHP传奇游戏推广信息发布站程序源码带会员发布

这是一个游戏导航网站程序。可以做任何一款游戏的推广发布&#xff0c;会员注册发布&#xff0c;后台审核通过&#xff0c;前台就可以展示&#xff0c;非常不错的游戏发布平台

一个项目学习Vue3---响应式基础

观察下面一段代码&#xff0c;学习响应式基础的全部内容 <template><div><div>将下面的msg属性放到上面来:{{ msg }}</div><button click"count">{{ count }}</button><button click"object.count.value">{{ o…

【Carsim】Carsim2019与Matlab2015b联合仿真测试

&#x1f60f;★,:.☆(&#xffe3;▽&#xffe3;)/$:.★ &#x1f60f; 这篇文章主要介绍Carsim2019与Matlab2015b联合仿真测试。 学其所用&#xff0c;用其所学。——梁启超 欢迎来到我的博客&#xff0c;一起学习&#xff0c;共同进步。 喜欢的朋友可以关注一下&#xff0c…

python-糖果俱乐部(赛氪OJ)

[题目描述] 为了庆祝“华为杯”的举办&#xff0c;校园中开展了许多有趣的热身小活动。小理听到这个消息非常激动&#xff0c;他赶忙去参加了糖果俱乐部的活动。 该活动的规则是这样的&#xff1a;摊位上有 n 堆糖果&#xff0c;第 i 堆糖果有 ai​ 个&#xff0c;参与的同学可…