1.堆排序算法
(1).原理
堆排序是一种选择排序,通过实现大小堆,来取出堆顶的数据,然后和最后一个交换,然后将堆的大小减一,循环这个过程直到,只有一个数据时停止。
升序建大堆,降序建小堆。
(2).问题:很多人会疑惑为什么要交换之后再减小堆的大小呢?难道不交换就不能筛选出我们要的极值吗?
首先向下调整算法的时间复杂度为O(log n )
数据一共是n个
先交换再减小,堆的结构变化不大,我们只需要执行一次向下调整算法,就可以重新建堆。
而直接取出堆顶的数据之后,堆的结构发生改变,重新建立堆的成本太大。
2.代码展示
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
void Swap(int *p1, int* p2)
{
int tmp = *p1;
*p1 = *p2;
*p2 = tmp;
}
//向下调整算法用于建堆
void AdjustDown(int* arr, int parent,int n)
{
assert(arr);
int child = 2 * parent + 1;
while (child<n)
{
if (child+1<n && arr[child] < arr[child + 1])
{
++child;
}
if(arr[parent] < arr[child])
{
Swap(&arr[parent], &arr[child]);
parent = child;
child = 2*parent+ 1;
}
else
{
break;
}
}
}
void HeapSort(int* arr, int n)
{
assert(arr);
for (int i = (n-2)/2; i >= 0; --i)
{
AdjustDown(arr, i, n);
}
int end = n-1;
while (end)
{
Swap(&arr[0], &arr[end]);
--end;
AdjustDown(arr, 0, end);
}
}
void Print(int* arr, int n)
{
for (int i = 0; i < n; i++)
{
printf("%d ", arr[i]);
}
printf("\n");
}
int main()
{
int arr[] = { 1,5,6,7,8,9,64,2,5,6,5,1,3,13,13,1,5,5,15 };
int n = sizeof(arr) / sizeof(arr[0]);
HeapSort(arr, n);
Print(arr, n);
system("pause");
return 0;
}
3.结果展示
4.复杂度分析
堆排序的时间复杂度为O(nlogn)
空间复杂度为O(1)
有兴趣可以去看看堆的实现