堆排序算法原理及c++实现
文章目录
- 准备知识
- MAX-HEAPIFY过程
- 建堆
- 堆排序算法
- 总结
准备知识
堆的结构可以分为最大堆和最小堆,是一个完全二叉树,而堆排序是根据堆的这种数据结构设计的一种排序。
所谓完全二叉树即叶节点只能出现在最下层和次下层,并且最下面一层的结点都集中在该层最左边的若干位置的二叉树。
存储一个完全二叉树,最适合使用数组,因为它相比链表不需要存储左、右子树的指针,更加节省内存空间,通过数组索引即可以随机访问到对应元素。
假设你知道某个节点下标为x ,那么其左子树下标为 x *2+1,其右子树下标为 x *2+2 ,其父节点下标为 (x-1)/2。
每个结点的值都大于其左孩子和右孩子结点的值,称之为最大堆(大根堆);
每个结点的值都小于其左孩子和右孩子结点的值,称之为最小堆(小根堆)。
如果把堆看成一棵树,我们定义一个堆中的节点的高度就为根节点到叶节点最长简单路径上边的数目。
MAX-HEAPIFY过程
MAX-HEAPIFY过程其时间复杂度为O(lgn),它是维护最大堆性质的关键。
MAX-HEAPIFY是用于维护最大堆性质的重要过程。它的输入为一个数组A和一个下标i。在调用MAX-HEAPIFY的时候,我们假定根节点为LEFT(i)和RIGHT(i)的二叉堆都是大根堆,但这时A[i]有可能小于其孩子,这样就违背了大根堆的性质。
MAX-HEAPIFY通过让A[i]的值在大根堆中逐级下降,从而是的以下标为i为根节点的字数重新遵循大根堆的性质。
//arr为堆,len为堆的长度,idx为非叶节点下标
void adjust(vector<int>& arr, int len, int idx) {int left = 2 * idx + 1;//idx的左子节点int right = 2 * idx + 2;//idx的右子节点int maxidx = idx;//maxidx为左右子节点及当前节点中最大的那个//判断最大节点是不是左右子节点if (left<len && arr[left]>arr[maxidx])maxidx = left;if (right<len && arr[right]>arr[maxidx])maxidx = right;if (maxidx != idx) {swap(arr[maxidx], arr[idx]);//交换根节点和子节点的值adjust(arr, len, maxidx);//交换后的子节点值为插入的节点的值,继续迭代}//else return;//如果最大的就是当前节点的值,则直接结束此次迭代
}
建堆
建堆具有线性时间复杂度O(n),功能是从无序的输入数据数组中构造一个最大堆。
在建堆的时候,我们可以用自底向上的方法利用过程MAX-HEAPIFY把一个大小为n的数组转换为大根堆。子数组A(n/2+1…n)中的元素都是树的叶节点。每个叶节点都可以看成只包含一个元素的堆。建堆的过程就是堆树中的其他节点都调用一次MAX-HEAPIFY:
for (int i = n / 2 - 1; i >= 0; i--)//MAX-HEAPIFY(A,i);adjust(arr, size, i);
堆排序算法
heapsort(堆排序)过程其时间复杂度为O(nlgn),功能是对一个数组进行原址排序。
初始的时候,堆排序算法利用建堆过程将输入数组A[1…n] 建成最大堆。
因为数组中的最大元素总在根节点A[1]上,通过把它与A[n]进行交换,我们可以让元素放到正确的位置上。
这时候,如果我们从堆中去掉节点n,剩余的节点中,原来根的左右子节点仍然是最大堆,而新的节点可能会违背最大堆的性质。
为了维护最大堆的性质,我们要做的是利用MAX-HEAPIFY过程重新在A[1…n-1]上构造一个最大堆。堆排序算法会不断重复这一过程,直到堆的大小从n-1降到2。
for (int i = size - 1; i >= 1; i--) {swap(arr[0], arr[i]);//交换根节点与最后一个节点adjust(arr, i, 0);//调整堆为最大堆}
详细图解可见这篇帖子的4.3.3利用大根堆进行排序
总结
完整的堆排序c++代码如下:
/*堆排序*/
#include<iostream>
#include<vector>
using namespace std;void heapSort(vector<int>& arr, int size);
void adjust(vector<int>& arr, int len, int idx);//递归方式构建大根堆(len是arr的长度,idx是当前节点的下标)
void adjust(vector<int>& arr, int len, int idx) {int left = 2 * idx + 1;//idx的左子节点int right = 2 * idx + 2;//idx的右子节点int maxidx = idx;if (left<len && arr[left]>arr[maxidx])maxidx = left;if (right<len && arr[right]>arr[maxidx])maxidx = right;if (maxidx != idx) {swap(arr[maxidx], arr[idx]);adjust(arr, len, maxidx);}
}void heapSort(vector<int>& arr, int size) {//构建大根堆,从最后一个节点的父节点开始向前遍历for (int i = size / 2 - 1; i >= 0; i--)adjust(arr, size, i);//调整大根堆for (int i = size - 1; i >= 1; i--) {swap(arr[0], arr[i]);adjust(arr, i, 0);}
}int main() {vector<int> arr = { 8, 1, 14, 3, 21, 5, 7, 10 };heapSort(arr, arr.size());return 0;
}
堆排序算法原理及c++实现相关推荐
- 堆排序算法原理及C++实现(详细注释)
1.算法原理 原理部分参考下面这个博客即可: 堆排序算法(图解详细流程) 2.C++实现: 解法一:利用vector实现最大堆 注意:heap_max这个函数调用了两次: 建堆时候和交换最大值之后分别 ...
- 堆排序 java_详解堆排序算法原理及Java版的代码实现
概述堆排序是一种树形选择排序,是对直接选择排序的有效改进. 堆的定义如下:具有n个元素的序列(k1,k2,...,kn), 当且仅当满足: 时称之为堆.由堆的定义可以看出,堆顶元素(即第一个元素)必为 ...
- 上标3下标6算法_图解堆排序算法
堆排序定义 一般来说,算法就像数学公式,前人经过不断优化和验证得到有规律性的公式留给后人使用,当然也会交给后人验证的思路.那么堆排序算法就是这样,它有基本固定的定义如下: 1.将数组构建为一颗有规则的 ...
- C++ 十大经典排序算法原理及模板之STL方法实现以及稳定性分析
写在前面: 1.本文中默认排序为升序,降序的原理类似. 2.如果程序直接复制到vs出现无法识别标记的问题,解决方法在这:vs无法识别标记的解决方法 3.本文的算法都是自己用stl实现的,疏漏之处还请指 ...
- dijkstra算法原理_这 10 大基础算法,程序员必知必会!
来源:博客园原文地址:http://kb.cnblogs.com/page/210687/算法一:快速排序算法快速排序是由东尼·霍尔所发展的一种排序算法.在平均状况下,排序n个项目要Ο(nlogn)次 ...
- java排序算法原理_排序算法原理与实现(java)
排序算法原理与实现(java) Java程序员必知的8大排序 [来源:本站 | 日期:2012年12月24日 | 浏览173 次] 字体:[大 中 小] 8种排序之间的关系: 1, 直接插入排序 (1 ...
- Java实现堆排序算法
堆排序是计算机编程中一种流行且高效的排序算法.学习如何编写堆排序算法需要了解两种类型的数据结构-数组和树. 我们要排序的初始数字集存储在数组中,例如[10, 3, 76, 34, 23, 32],排序 ...
- CRF(条件随机场)与Viterbi(维特比)算法原理详解
摘自:https://mp.weixin.qq.com/s/GXbFxlExDtjtQe-OPwfokA https://www.cnblogs.com/zhibei/p/9391014.html C ...
- 三维目标检测算法原理
三维目标检测算法原理 输入输出接口 Input: (1)图像视频分辨率(整型int) (2)图像视频格式(RGB,YUV,MP4等) (3)左右两边的车道线位置信息摄像头标定参数(中心位置(x,y) ...
最新文章
- physx选择显卡还是cpu_工控机如何选购cpu,工控机cpu选择盒装好还是散装好
- Spring Cloud 注册中心在tomcat中部署
- SQL Server LOWER Functions
- Codeforces Round #582 (Div. 3)
- 创建provider服务
- Linux中防火墙命令笔记
- awk 多文件操作2种实现方法
- html5音乐播放时间监测,【HTML5】HTML5中video元素事件详解(实时监测当前播放时间)...
- 移动开发痛点之一-接口验证之PostMan图文教程
- listen函数的第二个参数_signal(SIGPIPE,?SIG_IGN)listen函数中backlog参数分析
- Redis--blpop命令使用
- Python 字符串 循环
- python基础教程第三版pdf 脚本之家-一篇不错的Python入门教程
- Hadoop Web 控制台安全认证
- 深信服校园招聘安全攻防A卷
- MS office二级错题记录【3】
- 还在抱怨pandas运行速度慢?这几个方法会颠覆你的看法
- python输出古诗词_python爬取古诗文网
- CTF题之BUUCTF系列:BUUCTF Misc 二维码
- 智能汽车操作系统哪家强?黑莓QNX领跑,中兴/华为撑起中国方案