SCAU-8644堆排序 C++

Description

用函数实现堆排序,并输出每趟排序的结果

输入格式

第一行:键盘输入待排序关键的个数n
第二行:输入n个待排序关键字,用空格分隔数据

输出格式

第一行:初始建堆后的结果
其后各行输出交换堆顶元素并调整堆的结果,数据之间用一个空格分隔

思路:
构建堆和调整堆的方法相同。所以从输出格式来看,其实是将每一次调整堆之后的结果进行输出,排序完成之后再多调整一次堆(最后一次什么都没有调整到,只是方便写代码用来输出结果)即可。

调整堆的方法:
从最后一个非子叶的节点(在数组上表示为:i=len/2)开始,将该根节点和其两个子节点三者中最大的一个放在该根节点上,然后对该根节点的两个字节点再进行一次调整堆的操作,直到根节点没有子节点为止。(这里是一个递归的操作)。每调整完一个节点后,i - -,继续调整上一个根节点。
(这部分需要理清楚树的节点之间的关系,可以画一个图标上序号来看一下)。

每次调整完堆之后,将堆的根节点和最后一个节点交换,然后再继续调整。

代码如下:

#include <iostream>
#include <cstring>
#include <algorithm>
#include <math.h>
#include <cstdio>
#include <string>
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);
}
原文地址:https://www.cnblogs.com/kstar/p/13100463.html