scau 8644 堆排序

Description

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

输入格式

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

输出格式

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

输入样例

10
5 4 8 0 9 3 2 6 7 1

输出样例

9 7 8 6 4 3 2 5 0 1
8 7 3 6 4 1 2 5 0 9
7 6 3 5 4 1 2 0 8 9
6 5 3 0 4 1 2 7 8 9
5 4 3 0 2 1 6 7 8 9
4 2 3 0 1 5 6 7 8 9
3 2 1 0 4 5 6 7 8 9
2 0 1 3 4 5 6 7 8 9
1 0 2 3 4 5 6 7 8 9
0 1 2 3 4 5 6 7 8 9

堆排序,相对于前面的算法写起来有点难,但是认真思考后其实逻辑也是很清晰的。遇到比较难的算法我是不太喜欢看书的,因为书上全是文字,CSDN或者知乎上一些大佬写的真的很详细且易懂。

一、堆的性质

1、是一棵完全二叉树

2、每个结点的值都大于或等于其子结点的值,我们称其为大根堆;反之,成为小根堆。

二、堆的存储

一般用数组来表示堆(PS.我这里的数组从下标1开始) 

不难发现,下标为i的结点的左孩子结点对应下标为2i,右孩子结点对应下标为2i+1

下标为i的结点的父结点下标为i/2

 三、堆的操作

1、大根堆调整——使子结点永远小于其父结点

2、创建最大堆——重新排序

3、堆排序——将堆顶(即最大值)和无序序列的最后一个元素调换位置(下面详细解释)

我们知道,大根堆的堆顶记录是数组中的最大值,这样一来,我们每次选择无序序列中的最大值就会变简单,大概步骤如下:

(1)构建大根堆

(2)将根结点和无序序列的最后一个元素a[n]交换位置

(3)再从根结点到a[n-1]再次构建大根堆

(4)以此类推,知道无序序列只剩下一个元素为止


看到这里,不知道你有没有思路了呢?

如果还不太懂,那么来看看下面的详细步骤

(1)首先,建初堆。即把a[1]…a[n]建成大根堆

(2)然后,把堆顶元素a[1]和无序区的最后一个数a[n]交换,得到了一个新的无序区a[1]…a[n-1],和新的有序区a[n],并且a[1]…a[n-1]均小于a[n]

(3)交换堆顶元素和无序区的最后一个数后,它可能就不是大根堆了。所以我们要重新建大根堆。再重复(2)中的步骤。把a[1]和a[n-1]交换,得到新的无序区a[1]…a[n-2],和新的有序区a[n-1]…a[n]……直到无序区只剩下一个数为止

图我就不画了,我不太会电脑画图哈哈哈哈,可别光看,一定要动手写写画画。随便举个例子都行的啦,比如{1,2,3,4,5,6,7},虽然它是一个有序序列,但是不影响你演算啦。

//代码如下

//我觉得还是很好理解的,有不懂的地方可以在评论区提出来啦,一起学习~

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>

using namespace std;

int n,a[100005];

void print()
{
    for (int i=1;i<=n;i++)
        cout << a[i] << ' ';
    cout << endl;
}

void HeapAdjust(int Start,int End)//将a[S...E]调整为以a[S]为根的大根堆
{
    int dad=Start;
    int son=dad*2;
    while(son <= End)//子结点在范围内才能进行比较
    {
        if(son+1<=End && a[son]<a[son+1])
            son++;//选择大的子结点
        if(a[dad]>a[son])
            return ;
        else
        {
            swap(a[dad],a[son]);
            dad=son;
            son=dad*2;
        }
    }
}

void HeapSort()
{
    for(int i=n/2;i>=1;i--)
    {
        HeapAdjust(i,n);//初建堆
    }
    print();
    for(int i=n;i>1;i--)
    {
        swap(a[1],a[i]);
        HeapAdjust(1,i-1);
        print();//输出调整堆的结果
    }
}

int main()
{
    cin >> n;
    for(int i=1;i<=n;i++)
        cin >> a[i];
    HeapSort();
    return 0;
}

//这个知乎作者写的很详细很详细,要是没看懂我的就去看看它叭~

【算法】排序算法之堆排序 - 知乎 (zhihu.com)

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值