堆排序

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

/* 1).从小到大排序,建立最小堆
 * 然后每次删除顶部元素并将顶部元素输出或存储起来
 * 直到堆空为止
 * 2).从小到大排序,建立最大堆
 * 最大对建好后,最大元素在vec[1],vec[1]得放置末尾,需将vec[number]与vec[1]交换
 * 交换后还需将vec[1]向下调整保持堆的特性,需要将堆的大小减1,如此反复,直到堆的大小变成1
 */

static std::vector<int> * vec;
static int number;

void Swap(int & index1,int & index2)
{
    int temp = (*vec)[index1];
    (*vec)[index1] = (*vec)[index2];
    (*vec)[index2] = temp;

    return;
}

void SiftDown(int & index)
{
    int t, flag = 0;
    while (index*2<=number && flag==0)
    {
        //判断与左儿子的关系
        if ((*vec)[index]>(*vec)[index*2])
        {
            t = index * 2;
        }
        else
        {
            t = index;
        }

        //判断与右儿子关系
        if (index * 2 + 1 <= number)
        {
            if ((*vec)[index * 2 + 1] < (*vec)[t])
            {
                t = index * 2 + 1;
            }
        }

        //如果t与index不相等,说明子节点中有比父节点小的,交换两值
        if (t!=index)
        {
            auto * pS = Swap;
            pS(index,t);
            index = t;   //更换换下标,继续向下调整
        }
        else
        {
            flag = 1;     //说明当前父节点已经比两个子节点都要小了,不需要进行调整了
        }
    }
    
    return;
}

void Create()
{
    /*
    * 首先我们从叶结点开始,因为叶结点没有儿子,所以所有以叶节点为根结点的子树(只有一个结点)
    * 都符合最小堆的特性,即父节点的值比子节点的值小,叶节点连子节点都没有,当然符合
    * 因此所有叶节点都不需要处理,直接跳过,从第 (number/2)个结点开始处理
    */
    auto * pS = SiftDown;
    for (int i=number/2;i>=1;i--)
    {
        pS(i);
    }

    return;
}

int * DeleteMax()
{
    int  temp = (*vec)[1];
    (*vec)[1] = (*vec)[number];
    number--;
    int  p = 1;
    int & index = p;
    auto * pS = SiftDown;
    pS(index);

    return &temp;
}

//堆排序
void HeapSort()
{
    while (number<1)
    {
        int p = 1;
        int & index = p;
        Swap(index,number);
        number--;
        auto * pS = SiftDown;
        pS(index);
    }

    return;
}

int main()
{
    vec = new vector<int>();
    std::cin >> number;
    ::fill_n(::back_inserter(*vec), (number+1),0);
    for (int i = 1; i <= number; i++)
        std::cin >> (*vec)[i];

    auto * pC = Create;
    pC();

    int n = number;
    auto * pD = *DeleteMax;
    for (int i = 1; i <= n; i++)
        std::cout << *pD() << std::endl;

    delete vec;
    vec = nullptr;

    ::getchar(); ::getchar();
    return 0;
}

/*
测试用例:
14
99 5 36 7 22 17 46 12 2 19 25 28 1 92
*/



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值