堆排序(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); }
原文:http://blog.csdn.net/reage11/article/details/19288407