堆排序(Heapsort)是指利用堆这种数据结构所设计的一种排序算法。堆是一个完全二叉树的结构,并同时满足堆积的性质:即子结点的键值或索引总是小于(或者大于)它的父节点。
由于堆是一个完全二叉树的结构所以我们在存储的时,使用线性链表或者数组存储。
堆排序有最大堆或者最小堆。其实堆排序是一个递归的过程。让所有子树也是一个最小(或者最大)堆。
堆排序的过程有两步:
1. 建立最小(或最大)堆。
2. 将得到最小(或最大)值(第一个元素)与当前堆最后一个元素交换。堆中元素个数减一。如果堆中元素个数不为0,转到下一步
3. 这个时候堆可能已经违反最大(或最下)堆的性质了。进行最大(或最小)堆调整。
我们以最小堆最为例子讲解吧。
建立堆的过程,分析的时候我们是从上倒下,使用递归实现。
如图,节点左边的值表示在数组中存储的index,
如果,首先,我们将以节点3为根子树建立最小堆。
其次。我们将以节点2为根子树建立最小堆。
再次。我们将以节点1为根子树建立最小堆。
最后。我们将以节点0为根子树建立最小堆。就完成了建立堆的过程。
这样,我们就可以不使用递归了。
其实,其实我们只需要保证所有节点大有2子树为最小堆。也就是以节点3,2,1,0为根的子树。我们从index最大开始最小堆就行了。
问:其实我们只需要保证所有节点大有2子树为最小堆,这个index怎么算?
提示:注意堆是一个完全二叉树。使用二叉树的性质。节点数/2。
堆调整的过程与建堆的过中子树调整是一样的。
下面是最小堆的排序过程代码:
#include<stdio.h>
#include<stdlib.h>
#include <stdio.h>
#define MAX 200
void print_arr(int a[], int n);
int
heap_item_sort(int a[], int n, int len)
{
int tmp;
int i,j;
j = n;
tmp = a[j];
for(i = 2*n+1; i < len; i = i*2+1) {
if(i+1 < len && a[i] > a[i+1]) {
i++;
}
if( tmp > a[i] ) {
a[j] = a[i];
j = i;
}
else {
break;
}
}
a[j] = tmp;
return 0;
}
void
head_sort(int a[], int n)
{
int tmp ;
int i;
for(i = n/2 -1 ; i >=0; i--) {
heap_item_sort(a, i, n);
}
for(i = n-1; i >=0; i--) {
tmp = a[0];
a[0] = a[i];
a[i] = tmp;
heap_item_sort(a,0,i);
}
}
void
print_arr(int a[], int n)
{
int i = 0;
while(i < n) {
printf("%-5d|", a[i++]);
}
printf("\n");
}
int main()
{
int a[]={49, 38, 65, 97, 76, 13, 27,10 };
int n = sizeof(a)/sizeof(int);
printf("heap sort befor\n");
print_arr(a, n);
head_sort(a, n);
printf("heap sort result\n");
print_arr(a, n);
}
blog: http//www.rhttp.cn