排序6之堆排序
在进行堆排序之前必须知道堆的性质。
堆分为大根堆和小根堆,我们只说下大根堆,小根堆其实和大根堆没多大区别:
ki>=k(2i)且ki>=k(2i+1)(1≤i≤ n),当然,这是大根堆,小根堆则换成<=号。//k(i)相当于二叉树的非叶结点,K(2i)则是左孩子,k(2i+1)是右孩子
#include <stdlib.h>//堆排序
#include <stdio.h>
#include <string.h>
#define swap(x,y) {int t=x;x=y;y=t;}
#define N 10
int len;
void kph(int *a,int n)//堆的性质维护
{ //该函数实现前提是:以节点n的左右孩子为根的二叉树是堆
int k=n,l,r;
l=k*2; r=l+1;
if(r<=len)
{
if(a[l]<a[r])
swap(l,r);
if(a[l]>a[k])
{
swap(a[k],a[l]);
kph(a,l);
}
return ;
}
else
{
if(l<=len)
if(a[l]>a[k])
swap(a[l],a[k]);
return ;
}
}
void ch(int *a,int n)//堆的建立
{
int i,k;
scanf("%d",&a[1]);
for(i=2;i<=n;i++)
{
scanf("%d",&a[i]);
k=i;
while(k>1&&a[k]>a[k/2])
{
swap(a[k],a[k/2]);
k=k/2;
}
}
}
void hs(int *a,int n)//堆排序
{
len=n;
while(len>1)
{
swap(a[1],a[len]);
len--;
kph(a,1);
}
}
int main()
{
int i;
int a[N+1];
memset(a,0,sizeof(a));
ch(a,N);//堆的建立
hs(a,N);
for(i=1;i<=N;i++)
printf("%d ",a[i]);
printf("\n");
return 0;
}
--------江财小子