堆排序的思想和简单选择排序思想类似,都是通过不断地寻找最大值,实现数组的排序的。堆排序通过不断的将数组构造成大顶堆,实现排序。
这里出现了大顶堆这个名词,大顶堆的意思是有一个完全二叉树,每个节点的值都大于或者等于其左右孩子节点的值,这样的完全二叉树就是大顶堆。
我们看这样一个数组[90,70,80,60,10,40,50,30,20],首先将其图形化成为一个完全二叉树。
下面的任务就是取构造大顶堆。
构造大顶堆的方法如下:
注意:除了第一次构造大顶堆时,需要从下往上所有的子树都进行调整,后面构造大顶堆时,因为只有最上面的子树不符合要求,其他都是符合要求的,所以只需要对最上面的子树进行调整。这一点在代码中也有体现。
void HeapSort(List *L)
{
int i,j;
for(i=L->length/2;i>0;i--) /* 把L中的r构建成一个大根堆 */
HeapAdjust(L,i,L->length);
print(L);
for(i=L->length;i>1;i--)
{
swap(L,1,i); /* 将堆顶记录和当前未经排序子序列的最后一个记录交换 */
HeapAdjust(L,1,i-1); /* 将L->r[1..i-1]重新调整为大根堆 */
}
}
void HeapAdjust(List *L,int s,int m)
{
int temp,j;
temp=L->r[s];
for(j=2*s;j<=m;j*=2) /* 沿关键字较大的孩子结点向下筛选 */
{
if(jr[j]r[j+1])
++j; /* j为关键字中较大的记录的下标 */
if(temp>=L->r[j])
break; /* rc应插入在位置s上 */
L->r[s]=L->r[j];
s=j;
}
L->r[s]=temp; /* 插入 */
}
#include
#define MAXSIZE 10000
#define MAX_LENGTH_INSERT_SORT 7 /* 用于快速排序时判断是否选用插入排序阙值 */
#define N 9
typedef struct
{
int a[MAXSIZE+1];
int length;
}
SqList;
void swap(SqList *L,int i,int j);
void print(SqList *L);
void heapSort(SqList *L);
void heapAdjust(SqList *L,int s, int m);
void swap(SqList *L,int i,int j)
{
int temp = L->a[i];
L->a[i] = L->a[j];
L->a[j] = temp;
}
void print(SqList *L)
{
int i = 0;
for(i = 0; i < L->length; i++)
{
printf("%d,",L->a[i]);
}
printf("%d\n",L->a[i]);
}
void heapSort(SqList *L)
{
int i;
for(i = L->length/2; i>0 ; i--)
{
heapAdjust(L,i,L->length);
}
for(i = L->length;i > 1;i--)
{
swap(L,1,i);
heapAdjust(L,1,i-1);
}
}
void heapAdjust(SqList *L,int s, int m)
{
int j,temp;
temp = L->a[s];
for(j = 2*s; j <= m;j *= 2)
{
if(j < m && L->a[j] < L->a[j+1])
j++;
if(temp > L->a[j])
break;
L->a[s] = L->a[j];
s=j;
}
L->a[s] = temp;
}
int main()
{
int d[N]={50,10,90,30,70,40,80,60,20};
SqList test;
int i;
for(i=0;i