>>>八大排序总结(1)——冒泡排序(Bubble Sort)(c语言实现)<<<
>>>八大排序总结(2)——选择排序(Selection Sort)(c语言实现)<<<
>>>八大排序总结(3)——插入排序(Insertion Sort)(c语言实现)<<<
>>>八大排序总结(4)——快速排序(Quick Sort)(c语言实现)<<<
>>>八大排序总结(5)——归并排序(Merge Sort)(c语言实现)<<<
>>>八大排序总结(6)——希尔排序(Shell Sort)(c语言实现)<<<
>>>八大排序总结(8)——线性时间复杂度的排序(桶排序,基数排序,计数排序)【用空间换时间】(c语言实现)<<<
目录
堆排序(Bubble Sort)基本思想
堆排序(英语:Heapsort)是指利用堆这种数据结构所设计的一种排序算法。堆是一个近似完全二叉树的结构,并同时满足堆积的性质:即子结点的键值或索引总是小于(或者大于)它的父节点。
在堆的数据结构中,堆中的最大值总是位于根节点(在优先队列中使用堆的话堆中的最小值位于根节点)。堆中定义以下几种操作:
-
最大堆调整(Max Heapify):将堆的末端子节点作调整,使得子节点永远小于父节点
-
创建最大堆(Build Max Heap):将堆中的所有数据重新排序
-
堆排序(HeapSort):移除位在第一个数据的根节点,并做最大堆调整的递归运算
原理
首先,我们要构建最大堆
[1] 从最大的非叶节点(设为Key[i])开始,往下进行调整,如果子孩子节点Key[2*i+1]和Key[2*i+2]较大的值比Key[i]的值大,则,交换该节点Key[i]与子节点中较大的节点。然后 以交换后的子节点作为当前节点,往下进行调整,直到遇到叶节点;
[2] 最大非叶节点Key[i]调整完毕后,对节点Key[i-1]进行往下调整,直到出现叶节点;不断重复此过程,直到对根节点往下调整完毕;
下面是建大顶堆的实例:待排序数组为[5 16 3 20 17 4]
建好最大堆后就可以进行堆排序了,如下图所示
时间,空间复杂度与算法稳定性
1.时间复杂度:
最坏情况下时间复杂度:O(NlogN)
平均时间复杂度:O(NlogN)
2.空间复杂度:O(1)
3.稳定性:不稳定
代码+分析
//堆调整,构建大顶堆,arr[]是待调整的数组,i是待调整的数组
//元素的位置,length是数组的长度
void HeapAdjust(int arr[], int i, int length)
{
int Child;
int temp;
for(;2 * i + 1 < length; i = Child)
{
//子节点的位置 = 2 * (parent(父结点)) + 1
Child = 2 * i + 1;
//得到子结点中较大的结点
if(Child < length - 1 && arr[Child + 1] > arr[Child])
++Child;
//如果较大的子结点大于父结点那么把较大的子结点往上移动
//替换它的父结点
if(arr[i] < arr[Child])
{
temp = arr[i];
arr[i] = arr[Child];
arr[Child] = temp;
}
else
break;
}
}
//堆排序算法
void heap_sort(int arr[], int length)
{
int i;
//调整序列的前半部分元素,调整完之后第一个元素
//是序列的最大元素,length/2-1是最后一个非叶子结点
for(i = length/2 - 1; i >= 0; --i)
HeapAdjust(arr, i, length);
//从最后一个元素开始对序列进行调整,不断的缩小调整
//的范围直到第一个元素
//循环里是把第一个元素和当前的最后一个元素交换
//保证当前的最后一个位置的元素是现在这个序列的最大的
//不断的缩小调整heap的范围,每一次调整完毕保证第一个
//元素是当前序列的最大的元素
for(i = length - 1; i > 0; --i)
{
arr[i] = arr[0]^arr[i];
arr[0] = arr[0]^arr[i];
arr[i] = arr[0]^arr[i];
//此处通过异或运算交换arr[i]与arr[0]的值
HeapAdjust(arr, 0, i); //递归调整
}
}
欢迎大家评论指正,谢谢◕‿◕