Description
用函数实现堆排序,并输出每趟排序的结果
输入格式
第一行:键盘输入待排序关键的个数n
第二行:输入n个待排序关键字,用空格分隔数据
输出格式
第一行:初始建堆后的结果
其后各行输出交换堆顶元素并调整堆的结果,数据之间用一个空格分隔
思路:
构建堆和调整堆的方法相同。所以从输出格式来看,其实是将每一次调整堆之后的结果进行输出,排序完成之后再多调整一次堆(最后一次什么都没有调整到,只是方便写代码用来输出结果)即可。
调整堆的方法:
从最后一个非子叶的节点(在数组上表示为:i=len/2)开始,将该根节点和其两个子节点三者中最大的一个放在该根节点上,然后对该根节点的两个字节点再进行一次调整堆的操作,直到根节点没有子节点为止。(这里是一个递归的操作)。每调整完一个节点后,i - -,继续调整上一个根节点。
(这部分需要理清楚树的节点之间的关系,可以画一个图标上序号来看一下)。
每次调整完堆之后,将堆的根节点和最后一个节点交换,然后再继续调整。
代码如下:
#include
#include
#include
#include
#include
#include
typedef long long ll;
const int MAXL=10000+10;
using namespace std;
int a[MAXL]={0};
int n;
void printarr()
{
int i;
for(i=1;i<=n;i++)
{
cout<<a[i]<<" ";
}
cout<<endl;
}
void adjust(int i,int len)
{
int j;
if(a[i]<a[i*2+1]&&i*2+1<=len||a[i]<a[i*2]&&i*2<=len)//将该根节点和其两个子节点三者中最大的一个放在该根节点上//
{
if(a[i*2+1]>a[i*2]&&i*2+1<=len) //如果不加i*2+1<=len这一条件,会将已经排好序的放在了最后的节点也算进来//
{
j=i*2+1;
}
else
{
j=i*2;
}
swap(a[i],a[j]);
}
if(i*2+1<=len) //直到根节点没有子节点为止//
{
adjust(i*2+1,len); //然后对该根节点的两个字节点再进行一次调整堆的操作//
}
if(i*2<=len)
{
adjust(i*2,len);
}
}
void heapsort(int len)
{
int i;
for(i=len/2;i>=1;i--) //每调整完一个节点后,i - -,继续调整上一个根节点。//
{
adjust(i,len);
}
printarr();
swap(a[1],a[len]); //每次调整完堆之后,将堆的根节点和最后一个节点交换,然后再继续调整。//
if(len>1)
{
heapsort(len-1);
}
}
int main()
{
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>a[i];
}
heapsort(n);
}