前言
本篇文章记录了Python与C++的堆排序实现与讲解
以下是本篇文章正文内容,下面案例可供参考
一、选择排序是什么?
选择排序:每一趟在待排序元素中选取关键字最小(或最大)的元素加入有序子序列 ,主要分为"简单选择排序"和"堆排序".
二、什么是堆排序?
堆排序是指利用堆这种数据结构所设计的一种排序算法,每一趟将堆顶元素加入有序子序列(与待排序序列中的最后一个元素位置进行交换)
堆是一个近似完全二叉树的结构,并同时满足堆积的性质:即子结点的键值或索引总是小于(或者大于)它的父节点。”
- 若满足:L(i)≥L(2i)且L(i)≥L(2i+1) (1≤i≤n/2) --称为大根堆(大顶堆)
- 若满足:L(i)≤L(2i)且L(i)≤L(2i+1) (1≤i≤n/2) --称为小根堆(小顶堆)
- 在完全二叉树中,根≥左、右那么就是一个大根堆。
- 在完全二叉树中,根≤左、右那么就是一个小根堆。
三、算法思想
3.1 建立大根堆
给定一个初始序列,需要先构造一个大根堆
思路:把所有非终端节点都检查一遍,是否满足大根堆要求,如果不满足,则进行调整,非终端节点为L[1…n/2]的值,从后往前进行检查当前节点i是否满足根≥左、右孩子,若不满足,将当前节点与更大的孩子互换位置,具体看代码注释。
- i的左孩子 —2i
- i的右孩子 —2i+1
- i的父节点 —[i/2]
期间元素互换破坏了下一级的堆,则采用相同的方法,继续往下调整(期间小元素不断下坠)
3.2 基于大根堆排序
每一趟将堆顶元素加入子序序列(与待排序序列中最后一个元素交换位置),并将待排序序列再次调整为大根堆(小元素不断下坠的过程).
基于大根堆排序会获得一个递增的序列
四、动态演示
五、代码示例
5.1.C++代码示例
void HeapAdjust(int A[],int k,int len){
/*************************************************
Function: // BuildMaxHeap
Description: // 建立大根堆
Calls: // HeapAdjust;
Input: // A[]-被排序数组
// n -数组长度
Output: // None
Return: // None
*************************************************/
A[0]=A[k]; // A[0]暂存子树的根节点
for (int i=2*k; i <= len; i*=2) // 以k节点不断向下寻找较大节点
{
if (i<len && A[i] < A[i+1]) // 判断左右子树谁大
{
i++; // 当右子树大于左子树时i++,获取右子树的i值
}
if (A[0]>=A[i]) // 判断当前的根节点是否大于左右子树中的最大值
{
break; // 筛选结束
}
else{
A[k]=A[i]; // 将最大的A[i]替换k节点
k=i; // 修改k节点的值,便于继续向下筛选
}
}
A[k] =A[0]; // 将筛选到的节点值,放到最终位置
}
void BuildMaxHeap(int A[],int len){
/*************************************************
Function: // BuildMaxHeap
Description: // 建立大根堆,时间复杂度为O(n)
Calls: // HeapAdjust;
Input: // A[]-被排序数组
// n -数组长度
Output: // None
Return: // None
*************************************************/
for(int k=len/2;k>0;k--){ // 从后往前调整所有非叶子节点
HeapAdjust(A,k,len); // 小元素下坠的过程
}
}
void swap(int &a,int &b){
int temp; // 用于交换的临时变量
temp=a;
a=b;
b=temp;
};
void HeapSort(int A[],int len){
/*************************************************
Function: // HeapSort
Description: // 对数组进行堆排序
Calls: // swap; BuildMaxHeap; HeapAdjust;
Input: // A[]-被排序数组
// n -数组长度
Output: // None
Return: // None
Others: // 堆排序
*************************************************/
BuildMaxHeap(A,len); // 第一次建立大根堆
for (int i = len; i >1; i--) // n-1一次交换与建堆过程
{
swap(A[1],A[i]); // 堆顶元素与堆底元素交换
HeapAdjust(A,1,i-1); // 把剩余待排序的元素整理成大根堆
}
}
5.2.Python代码示例
与C++一致,不再赘述。
六、性能分析
6.1 空间复杂度
空间复杂度=O(1)
6.2 时间复杂度
6.2.1 最坏时间复杂度
建堆时间复杂度=O(n)
排序的时间复杂度=O(n)+
n
l
o
g
2
n
nlog_2n
nlog2n=
n
l
o
g
2
n
nlog_2n
nlog2n
6.4 稳定性
堆排序是一个不稳定的排序算法