堆排序
本次排序结果为非递减,采用的是大顶堆。
思想
小顶堆调整:
假设输出堆顶元素之后,以堆中最后一个元素替代之,此时根节点的左右值比较,由于左子树根节点的值大于右子树的根节点的值且大于根节点的值,则将27和97交换,由于97替代了27之后破坏了右子树的堆,则需要进行上述相同的调整,直至叶子节点,此时堆顶为n-1个元素中的最大值,重复上述过程,将堆顶元素27和堆中最后一个元素97交换,得到新堆。
筛选:
从一个无序序列建堆的过程就是一个反复筛选过程。若将此序列看成是一个完全二叉树,则最后一个非终端点是第n/2个元素,由此筛选只需从第n/2个元素开始。
#include<stdio.h>
#define MAXSIZE 20 //数组大小
typedef int KeyType; //关键字类型
typedef int InfoType; //元素信息类型
//数组中元素的信息
typedef struct{
KeyType key; //元素排序的关键字
InfoType otherinfo; //元素信息
}RedType;
//数组的类型
typedef struct{
RedType r[MAXSIZE+1];
int length;
}SqList;
typedef SqList HeapType; //堆类型
int count=0;
//初始化待排序列
void Init(SqList *L,int a[],int length)
{
int i;
RedType rt;
for(i = 0;i < length;i++){
rt.key = a[i];
rt.otherinfo = i;
L->r[i] = rt;
}
L->length = length;
}
//交换堆中元素
void swap(RedType *p,RedType *q){
RedType temp = *p;
*p = *q;
*q = temp;
}
//打印堆
void print(HeapType *L){
int j,k=1,l,m=1;
for(l = L->length/2-(m++);l>=0;l--)
printf(" ");
for(j = 1;j < L->length;j++){
printf("%d ",L->r[j].key);
if(j == k){
printf("\n");
k=2*k+1;
for(l = L->length/2-(m++);l>=0;l--)
printf(" ");
}
}
}
//调整堆
void HeapAdjust(HeapType *H,int s,int m){
int j;
RedType rc;
rc = H->r[s];
for(j = 2*s;j<=m;j*=2){
if(j < m && H->r[j].key < H->r[j+1].key)
++j;
if(rc.key >= H->r[j].key)
break;
H->r[s] = H->r[j];
s = j;
}
H->r[s] =rc;
}
//堆排序
void HeapSort(HeapType *H){
int i;
for(i = (H->length-1)/2;i>0;--i)
HeapAdjust(H,i,H->length-1);
for(i = H->length-1;i>1;--i){
printf("\n第%d趟排序后的堆:\n",++count);
print(H);
printf("\n");
swap(&(H->r[1]),&(H->r[i]));
HeapAdjust(H,1,i-1);
}
}
int main(){
HeapType L;
int i;
int a[9] = {0,49,38,65,97,76,13,27,49};
Init(&L,a,9);
printf("排序前:");
for(i = 0;i < 9;i++){
printf("%-2d ",L.r[i].key);
}
printf("\n下标号:");
for(i = 0;i < 9;i++){
printf("%-2d ",L.r[i].otherinfo);
}
printf("\n");
print(&L);
HeapSort(&L);
printf("\n\n排序后:");
for(i = 0;i < 9;i++){
printf("%-2d ",L.r[i].key);
}
printf("\n下标号:");
for(i = 0;i < 9;i++){
printf("%-2d ",L.r[i].otherinfo);
}
printf("\n\n");
return 0;
}