排序有很多种方法,堆排序是其中的一种。它是选择排序的一种。可以利用数组的特点快速定位指定索引的元素。
堆有一个很好的性质:第i个位置上的值小于第2*i个位置上和第2*i+1个位置上的值(i<2*i && i<2*i+1),这种堆称为小根堆;第i个位置上的值大于第2*i个位置上和第2*i+1个位置上的值(i<2*i && i<2*i+1),这种堆称为大根堆。而第i个位置正好是第2*i个位置和2*i+1个位置的父母结点。
小根堆排序后是从大到小,大根堆排序后是从小到大。
我们先把准备工作做好
#include <stdio.h>
#include <stdlib.h>
#include<math.h>
#define MAX_SIZE 100
typedef char InfoType;
typedef struct Sz
{
int key;
InfoType *info;
}Sz;
typedef struct SQ//定义一个顺序线性表
{
Sz *R;
int length;
}SqList;
int Init_SqList(SqList *L)//顺序线性表初始化
{
L->R=(Sz *)malloc((MAX_SIZE + 1) * sizeof(Sz)) ;
if(!L->R)
return 0;
else
{
L->length = 0;
return 1;
}
}
要对一个数组进行堆排序,首先要建立一个堆。
void Heap_adjust(SqList *L, int s, int m)
{
/*H->R[s…m]中记录关键字除H->R[s].key均满足堆定义*/
/*调整H->R[s]的位置使之成为小根堆*/
int j = s;//起始位置
int k = 2 * j;/*计算H->R[j]的左孩子的位置*/
L->R[0] = L->R[j];/*临时保存H->R[j]*/
for (k = 2 * j; k <= m; )//k = 2*k
{
if(((k + 1) <= m) && (L->R[k].key > L->R[k + 1].key))
k++;/*选择左、右孩子中关键字的最的一个*/
if(L->R[k].key < L->R[0].key)
{
L->R[j] = L->R[k];
j = k;
k = 2 * j;
}
else
{
break;
}
}
L->R[j] = L->R[0];
}
然后把第一个元素和最后一个元素交换,交换之后可能就把堆打乱了,所以要重新在建立一个堆。这样交换n-1次,数组就有序了。
void Heap_Sort(SqList *L)
{
int i;
int j;
for(j = L->length/2; j > 0; j--)
Heap_adjust(L, j, L->length);/*初始建堆*/
for(j = 1; j <= L->length; j++)
{
printf("%d ", L->R[j].key);
}
printf("\n");
printf("------------------------------\n");
int k = L->length;
//需要进行n-1次交换
for(j = k; j > 1; j--)
{
L->R[0] = L->R[1];
L->R[1] = L->R[k];
L->R[k] = L->R[0];/*堆顶与最后一个交换*/
k--;/*每交换一次,长度减一,把最后一个元素除去*/
printf("%d\n", k);
if(j != 1)
{
for(i = ceil(k / 2); i > 0; i--)
Heap_adjust(L, i, k);/*建堆*/
}
for(i = 1; i <= k; i++)
{
printf("%d ", L->R[i].key);
}
printf("\n");
}
}
主方法
int main()
{
int i;
int num;
SqList L;
Init_SqList(&L);
/*输入数组*/
printf("please enter the number of the data:");
scanf("%d", &num);
for(i = 1; i < num + 1; i++){
int values;
printf("please enter the %d data:", i);
scanf("%d", &values);
L.R[i].key = values;
L.length++;
}
for(i = 1; i <= L.length; i++)
{
printf("%d ", L.R[i].key);
}
printf("\n");
printf("-------------create heap----------------\n");
Heap_Sort(&L);
printf("-------------after heap sort----------------\n");
for(i = 1; i <= L.length; i++)
{
printf("%d ", L.R[i].key);
}
printf("\n");
return 0;
}
例:
运行结果: