堆排序(heapsort)是指利用堆这种数据结构的一种排序算法。堆是一个完全二叉树的结构,即堆结构除最后一层外,其他各层都是满的,且最后一层的结点都靠在左边,并同时满足子结点的值总是小于或者大于它的父结点的值。
堆的基本操作:
1.向堆中插入一个元素
向有n个元素的堆中插入一个新元素,应当把元素放在n+1号结点,然后与其父结点比较大小,若大于其父结点,则保持了堆的性质,否则与其父结点交换,再向上比较,重复上述过程,直至不发生交换为止。
2.删除最小元素
直接删除根结点,把最后一个结点移动到根结点位置上,此时检查是否满足堆的性质,如果根结点比其儿子结点大,则与儿子结点中较小的一个交换,再向下比较,重复上述过程,直至不发生交换为止。
上述在插入操作中运用到了向上调整,在删除操作中运用到了向下调整,时间复杂度都是O(logn)的。
堆排序步骤:
(1)建堆,将所有结点布置成堆结构;
(2)取出堆顶结点,放入列表末尾;
(3)把堆尾的结点移动至顶部,调整此结点;
(4)跳转至(2)步骤,直至堆为空。
#include<cstdio>
using namespace std;
#define max 100000
int a[max],n,i,tot,t;
void down(int i)
{
int t,j;
while (i<=tot/2)
{
j=2*i;
if ((j<tot) && (a[j+1]<a[j]))
j++;
if (a[i]>a[j])
{
t=a[i];
a[i]=a[j];
a[j]=t;
i=j;
}
else
break;
}
}
int main()
{
scanf("%d",&n);
for (i=1;i<=n;i++)
scanf("%d",&a[i]);
tot=n;
for (i=n/2;i>=1;i--)
down(i);
for (i=1;i<=n;i++)
{
t=a[1];
a[1]=a[tot];
a[tot]=t;
tot--;
down(1);
}
for (i=n;i>=1;i--)
printf("%d ",a[i]);
return 0;
}