/*
基本思想
{
选择排序:每一趟在后面n-i+1个待排序元素中选取关键字最小的元素,作为有序子序列的第i个元素,直到n-i趟做完,待排序元素只剩下1个,就不用再选了。(堆排序为例)
堆排序步骤(大根堆为例):
{
基本思想:首先将表中的n个元素建成初始堆,根据堆本身的特点可知,栈顶元素就是最大值。输出栈顶元素后,通常将堆底元素送入栈顶,但这时候根节点可能不满足堆的性质
堆被破坏,将栈顶元素向下调整使得其继续保持大顶堆的性质,在输出栈顶元素,如此重复,直到堆中仅剩一个元素为止。
可见堆排序需要解决俩个问题:
1.如何将无序序列构造成初始堆
2.输出栈顶元素后,如何将剩余元素调整成新的堆
}
堆排序算法分析:
{
空间效率:使用了常数个辅助单元,空间复杂度为O(1)
时间复杂度为O(nlog2(n))
稳定性:不稳定
}
}
*/
#include<stdio.h>
#include<stdlib.h>
#define size 9
typedef struct
{
int data[size];
int length;
}sqlist;
//初始化顺序表
void inist(sqlist &s)
{
int yuan[size-1]={57,45,78,41,12,60,53,19};
s.data[0]=0; //作为暂存单元
s.length=size-1;
for(int i=1;i<=s.length;i++)
s.data[i]=yuan[i-1];
}
//输出顺序表
void pirintlist(sqlist s)
{
int i;
for(i=1;i<=s.length;i++)
{
printf("%d ",s.data[i]);
}
}
//建立大根堆
void headajust(sqlist &s,int k,int len)
{
s.data[0]=s.data[k];
for(int i=2*k;i<=len;i*=2)
{
if(i<len&&s.data[i]<s.data[i+1]) //这里比较孩子结点最大的一个
i++;
if(s.data[0]>=s.data[i]) //如果孩子结点小于双亲结点,无需要交换
break;
else
{ //否则,将双亲结点的值替换掉成最大的孩子结点,并记录他的位置
s.data[k]=s.data[i];
k=i;
}
}
s.data[k]=s.data[0]; //将交换最大孩子结点的位置上,放入交换的双亲结点
}
void buildmaxheap(sqlist &s,int len)
{
for(int i=len/2;i>0;i--) // 从【n/2】~1 反复调整堆
{
headajust(s,i,len);
}
}
//堆排序算法
void heapsort(sqlist &s,int len)
{
int temp,i,f=1;
buildmaxheap(s,len);
for(i=len;i>1;i--)
{
temp=s.data[i]; //每次将最大的元素(下标为1)与数组下表i的元素交换,使得最大,次大元素放到数组最后
s.data[i]=s.data[1];
s.data[1]=temp;
headajust(s,1,i-1); //交换后,从1~i的表中重新建立堆
printf("\n第%d趟排序表内容为:\n",f++);
pirintlist(s);
}
}
int main()
{
sqlist s;
inist(s);
printf("无序序列表内容为:\n");
pirintlist(s);
heapsort(s,s.length);
printf("\n排序后列表内容为:\n");
pirintlist(s);
return 0;
}
代码运行图