算法描述
将待排序序列构造成一个大根堆,此时,整个序列的最大值就是堆顶的根节点。将其与末尾元素进行交换,此时末尾就为最大值。然后将剩余n-1个元素重新构造成一个堆,这样会得到n个元素的次小值。如此反复执行,便能得到一个有序序列了
- 构造初始堆。将给定无序序列构造成一个大顶堆(一般升序采用大顶堆,降序采用小顶堆)。
- 将堆顶元素与末尾元素进行交换,使末尾元素最大。然后继续调整堆,再将堆顶元素与末尾元素交换,得到第二大元素。如此反复进行交换、重建、交换。
算法排序:
给9 4 7 34 21 33 8 0 67 6排序
第一次大根堆:
父 —> 子 n: 2n+1 2n+2
子 —> 父 n: (n-1)/2
第一次大根堆:从最后一颗子树开始,从后往前多次调整
一次堆调整:从上往下调整
时间复杂度
堆排序
时间复杂度:O(nlogn)
空间复杂度:O(1)
不稳定
第一次大根堆:
时间复杂度:O(nlogn)
空间复杂度:O(1)
不稳定
一次堆调整:
时间复杂度:O(logn)
空间复杂度:O(1)
代码实现:
#include <stdio.h>
#include <stdlib.h>
//一次堆调整
void HeapAdjust(int *arr,int start,int end)//O(logn),O(1)
{
int tmp = arr[start];
int i;
for(i=2*start+1;i<=end;i=2*i+1)
{
if(i+1<=end && arr[i]<arr[i+1])//i是左右孩子较大值的下标
i++;
if(tmp < arr[i])//arr[i]需要上移
{
arr[(i-1)/2] = arr[i];
}
else //找到位置
{
break;
}
}
arr[(i-1)/2] = tmp;
}
void HeapSort(int *arr,int len)//O(nlogn),O(1),不稳定
{
//第一次建大根堆
for(int i=(len-1-1)/2;i>=0;i--)
{
HeapAdjust(arr,i,len-1);
}
int tmp;
for(int i=0;i<len-1;i++)
{
tmp = arr[0];
arr[0] = arr[len-1-i];
arr[len-1-i] = tmp;
HeapAdjust(arr,0,len-1-i-1);
}
}
int main()
{
int arr[] = {4,9,0,12,34,67,8,91,32,54,66,88,2};
HeapSort(arr,sizeof(arr)/sizeof(arr[0]));
Show(arr,sizeof(arr)/sizeof(arr[0]));
return 0;
}