堆排序算法原理及c++实现

article/2025/10/29 15:27:45

文章目录

    • 准备知识
    • 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;
}

http://chatgpt.dhexx.cn/article/9Rm3A6Pv.shtml

相关文章

堆排序算法设计与分析

堆排序(HeapSort)是指利用堆积树(堆)这种数据结构所设计的一种排序算法&#xff0c;它是选择排序的一种。堆分为大根堆和小根堆&#xff0c;是完全二叉树。大根堆要求父结点的值大于或等于子结点的值&#xff0c;小根堆相反。根据大根堆的性质&#xff0c;我们可以知道最大值一…

堆排序算法实现

堆排序:结构逻辑上是完全二叉树,但是可以使用顺序存储来实现 一些二叉树的区别: 二叉树:度数最大为2并且每个子树也是二叉树 满二叉树:每层节点都是满的,没有空缺,也就是,叶子节点只能出现在最后一层 完全二叉树:限制条件比满二叉树弱化,只需要前k-1层是满二叉树结构,最后…

数据结构之堆排序算法详解+C语言实现

堆   堆是具有以下性质的完全二叉树&#xff1a;每个结点的值都大于或等于其左右孩子结点的值&#xff0c;称为大顶堆&#xff1b;或者每个结点的值都小于或等于其左右孩子结点的值&#xff0c;称为小顶堆。 堆排序   堆排序是利用堆这种数据结构而设计的一种排序算法&…

堆排序算法原理及实现

堆排序是排序中一种比较重要的算法&#xff0c;和快速排序一样&#xff0c;其复杂度也是O(nlogn)&#xff1b;同时也是一种原地排序算法&#xff1a;在任何时候&#xff0c;数组中只有常数个元素存储在输入数组以外。堆这种数据结构是处理海量数据比较常见的结构&#xff0c;海…

堆排序算法Java

基本原理 1):将带排序的序列构造成一个大顶堆&#xff0c;根据大顶堆的性质&#xff0c;当前堆的根节点&#xff08;堆顶&#xff09;就是序列中最大的元素 2):将堆顶元素和最后一个元素交换&#xff0c;然后将剩下的节点重新构造成一个大顶堆&#xff1b; 3):重复步骤2 小知识…

堆排序算法详细分析

一、堆相关概念 1.堆 堆是完全二叉树&#xff0c;即除最后一层外&#xff0c;其它层都是满的&#xff0c;且最后一层从左到右依次都有元素。如下图所示。 堆是用数组来实现的&#xff0c;图中下标就为数组的下标&#xff0c;其对应数组[5, 1, 7, 2, 8, 6, 3, 9, 4]&#xf…

数据结构——堆排序(算法)

基本介绍 1&#xff09;、堆排序是利用堆这种数据结构而设计的一种排序算法&#xff0c;堆排序是一种选择排序&#xff0c;它的最好、最坏、平均时间复杂度均为O(nlogn)&#xff0c;它也是不稳定排序。2&#xff09;、堆是具有以下性质的完全二叉树&#xff1a;每个节点的值都…

C++:堆排序算法详解

图解排序算法(三)之堆排序 预备知识 堆排序 堆排序是利用堆这种数据结构而设计的一种排序算法&#xff0c;堆排序是一种选择排序&#xff0c;它的最坏&#xff0c;最好&#xff0c;平均时间复杂度均为O(nlogn)&#xff0c;它也是不稳定排序。首先简单了解下堆结构。 堆 堆是具有…

排序算法:堆排序算法实现及分析

堆排序介绍 堆排序&#xff08;Heap Sort&#xff09;就来利用堆&#xff08;假设利用大顶堆&#xff09;进行排序的方法。它的基本思想是&#xff0c;将待排序的序列构成一个大顶堆。此时&#xff0c;整个序列的最大值就是堆顶的根结点。将它移走&#xff08;其实就是将其与堆…

堆排序算法 总结

最近面试&#xff0c;老是被问到堆排序算法。 回答时老是感觉思路不清楚&#xff0c;现在总结一下&#xff0c;把思路弄清楚的。 1.堆排序是利用堆的特性对记录序列进行排序的一种排序方法。 好的那么堆得特性是什么呢&#xff1f; 堆得定义&#xff1a; 堆是满足下列性质的数…

Java实现堆排序算法

堆排序是计算机编程中一种流行且高效的排序算法。学习如何编写堆排序算法需要了解两种类型的数据结构-数组和树。 我们要排序的初始数字集存储在数组中&#xff0c;例如[10, 3, 76, 34, 23, 32]&#xff0c;排序后&#xff0c;我们得到一个排序后的数组[3,10,23,32,34,76] 堆排…

精通八大排序算法系列:二、堆排序算法

精通八大排序算法系列&#xff1a;二、堆排序算法 作者:July 、二零一一年二月二十日本文参考&#xff1a;Introduction To Algorithms&#xff0c;second edition。------------------- 此精通排序算法系列&#xff0c;前一节&#xff0c;已讲过了一、快速排序算法&#xff0c…

堆排序算法详解

一、堆排序算法原理和动态图解 将待排序的序列构造成一个大顶堆。此时&#xff0c;整个序列的最大值就是堆顶的根节点。将它移走(其实就是将其与堆数组的末尾元素交换&#xff0c;此时末尾元素就是最大值)&#xff0c;然后将剩余的n-1个序列重新构造成一个堆&#xff0c;这样就…

【堆排序算法】(C语言实现)

堆排序 一.堆排序1.堆的概念及性质1.1堆的概念1.2堆的性质 二.向下调整和向上调整两大算法1. 向下调整算法2.1 向下调整算法基本思路 2. 向上调整算法2.2 向上调整的基本思路 三.堆的实现&#xff08;小堆&#xff09;1.头文件包含2. 接口实现 四.任意树调整为堆&#xff08;小…

堆排序算法

堆排序 堆排序&#xff08;Heapsort&#xff09;是指利用堆这种数据结构所设计的一种排序算法。堆积是一个近似完全二叉树的结构&#xff0c;并同时满足堆积的性质&#xff1a;即子结点的键值或索引总是小于&#xff08;或者大于&#xff09;它的父节点。 基本思想 利用大顶堆…

3.图解排序算法(三)之堆排序

作者&#xff1a; dreamcatcher-cx 出处&#xff1a; http://www.cnblogs.com/chengxiao/ 本文版权归作者和博客园共有&#xff0c;欢迎转载&#xff0c;但未经作者同意必须保留此段声明&#xff0c;且在页面明显位置给出原文链接。 原文链接&#xff1a;https://www.cnblogs.…

排序算法:堆排序

相关博客&#xff1a; 排序算法&#xff1a;冒泡排序、插入排序、选择排序、希尔排序 排序算法&#xff1a;归并排序、快速排序 排序算法&#xff1a;桶排序、计数排序、基数排序 排序算法&#xff1a;堆排序 十大排序算法小结 一、堆&#xff1a; 1、什么是堆&#xff1…

排序算法 —— 堆排序(图文超详细)

文章目录 堆排序1. 排序思路2. 如何建成大根堆2.1. 将待排序的数据看成一个完全二叉树。2.2. 建堆思想2.3. 建堆步骤2.3.1.先将最后一棵子树建成大根堆2.3.2.将其余子树建成大根堆2.3.3. 代码分析 3 如何实现堆排序3.1 排序思路3.2 代码实现的思路3.3 代码分析3.4 排序过程 4. …

十大经典排序算法----堆排序(超详细)

目录 1. 堆排序的基础知识 1.1 大顶堆&&小顶堆 1.2 向下调整算法 1.3 物理结构与逻辑结构的关系 2. 堆排序详解 2.1 堆排序整体思路 2.2 思路详解 2.2.1 建堆 2.2.2 大堆or小堆 2.2.3 输出数据 3. 时间复杂度分析 4. 完整代码 5. 彩蛋 1. 堆排序的基础知识…

【转载】堆排序算法(图解详细流程)

堆排序的时间复杂度O(N*logN),额外空间复杂度O(1)&#xff0c;是一个不稳定性的排序 目录 一 准备知识 1.1 大根堆和小根堆 二 堆排序基本步骤 2.1 构造堆 2.2 固定最大值再构造堆 三 总结 四 代码 一 准备知识 堆的结构可以分为大根堆和小根堆&#xff0c;是一个完全…