排序-堆排序

前言

计算机科学家,

图灵奖得主,

前后断言法的创始人

堆排序算法和Floyd-Warshall算法的创始人之一,

同时,他还是

有芝加哥大学文学士学位(有点抽象)

登场!!!

这位大佬自学成才(自学计算机)

基本思想

  1. 建立一个大堆(升序建大堆)
  2. 将堆顶元素与最后一个元素交换
  3. 交换后堆元素减一,重新调整堆

图1是我们准备的大堆,物理结构为

此时我们首尾交换

最大的数字就在数组的最后,他的位置就不用动了,

然后把最后一个数字剔除,将剩余的数字重新组成大堆,

以此类推,直至数组变为有序。

如何将一个数组变为大堆

随意列出一个堆

第一步

序号5向下调整,

使5,9序号所在分支变为大堆

这里本身就是大堆所以不动

第二步

序号4向下调整,

使4,7,8序号所在分支变为大堆

这里本身就是大堆所以不动



第三步

序号2向下调整,

使2,4,5,7,8,9序号所在分支变为大堆

第四步

序号3向下调整,

使3,6序号所在分支变为大堆

这里本身就是大堆所以不动

最后一步

从序号1向下调整,

将整个数组变为大堆

代码实现

1.将数组建立为大堆

    //找最后一个节点的父节点,一个数的父节点是(n-1)/2,最后一个节点是n-1
    for (int i = (n - 2) / 2; i >= 0 ; i--)
    {
        Adjustdown(f, n, i);
    }

2.向下调整函数

void Adjustdown(vector<int>& f,int n,int parent)
{
    //假设左孩子小
    int child = parent*2 + 1;

    while (child<n)//确保孩子存在
    {    //找出大孩子
        if (child + 1<n && f[child] < f[child + 1])
        {
            child++;
        }
        if (f[child] > f[parent])
        {
            swap(f[child], f[parent]);
            parent = child;
            child = parent * 2 + 1;
        }
        else
            break;
    }
}

3.依次选数,调堆

    while (end>0)
    {
        //选数
        swap(f[0], f[end]);
        //调堆
        Adjustdown(f, end, 0);
        end--;
    }

完整代码

void Adjustdown(vector<int>& f,int n,int parent)
{
    //假设左孩子小
    int child = parent*2 + 1;

    while (child<n)//确保孩子存在
    {    //找出大孩子
        if (child + 1<n && f[child] < f[child + 1])
        {
            child++;
        }
        if (f[child] > f[parent])
        {
            swap(f[child], f[parent]);
            parent = child;
            child = parent * 2 + 1;
        }
        else
            break;
    }
}

void HeapSort(vector<int>& f,int n)
{
    //找最后一个节点的父节点,一个数的父节点是(n-1)/2,最后一个节点是n-1
    for (int i = (n - 2) / 2; i >= 0 ; i--)
    {
        Adjustdown(f, n, i);
    }

    int end = n - 1;
    while (end>0)
    {
        //选数
        swap(f[0], f[end]);
        //调堆
        Adjustdown(f, end, 0);
        end--;
    }
}

从升序到降序的思考

仅仅需要将讲个小于大于颠倒一下即可,

逻辑很简单,大家思考一下。

但是不推荐

拿我们上面举例的数组说明:
从序号开始,剩下的数看做一个堆
但是在这之前建立好的堆关系全部乱了
需要重新建堆才能选出次小数!

总结

建立小堆排升序是可以的
但是效率很低没有体现优势

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值