原理:
堆排序就是利用堆(大顶堆)进行排序的方法,基本思想是,将待排序的序列构造成一个大顶堆。此时,整个序列的最大值就是堆顶的根节点。将它移走(将其与堆数组的末尾元素交换,此时的末尾元素就是最大值),然后将剩余的n-1 个序列重新构造成一个堆,这样就会得到n个元素的次小值。如此反复执行,就能得到一个有序序列了。
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#include <unistd.h>
void show(int *arr, int);//显示序列
void arr_init(int *arr, int);//待排序序列初始化
void swap(int *i, int *j)
{
int tep = *i;
*i = *j;
*j = tep;
}
void max_heapify(int *arr, int start, int end)
{
// 堆顶开始,父节点是堆顶
int dad = start;
int son = dad * 2 + 1; //子节点
while (son <= end)
{ // 若子節點指標在範圍內才做比較
if (son + 1 <= end && arr[son] < arr[son + 1]) // 两个子节点选择大的子节点
son++;
if (arr[dad] > arr[son]) // 如果父节点大于子节点,代表跳转完毕,退出
return;
else { // 否则交换父子节点,再和孙节点比较
swap(&arr[dad], &arr[son]);
dad = son;
son = dad * 2 + 1;
}
}
}
void heap_sort(int *arr, int len) {
// 初始化,i从最后一个父节点开始调整,
//因为叶子节点已经是一个堆了,所以从len/2开始 ,直到根节点0
for (int i = len / 2 - 1; i >= 0; i--)
max_heapify(arr, i, len - 1);
// 第一个元素已经排序好,放到最后面去,然后调整前面的i-1个元素
for (int i = len - 1; i > 0; i--)
{
swap(&arr[0], &arr[i]);
max_heapify(arr, 0, i - 1);
}
}
int main(int argc, char *argv[])
{
srand(time(0));
int len;
printf("input len:");
scanf("%d", &len);
int arr[len];
arr_init(arr, len);
show(arr, len);
heap_sort(arr, len);
show(arr, len);
return 0;
}
void arr_init(int *arr,int n)
{
for(int i = 0; i < n; i++)
{
arr[i] = rand()%100;
}
}
void show(int *arr, int n)
{
for(int i = 0; i < n; i++)
printf("%-3d ", arr[i]);
printf("\n");
}