还在用老掉牙的冒泡排序吗?快试试堆排序吧!


前言

冒泡排序具有很强的局限性,在具体使用的时候并不方便

例如:冒泡排序的时间复杂度为O(N^2),也就代表着100w的数据,如果用冒泡排序的话,需要进行1w亿次


为了提高排序的速度,我们可以采用堆排序

一、堆排序的思路

利用堆的性质
大堆:每个结点的值都大于或等于其左右孩子结点的值
小堆 :每个结点的值都小于或等于其左右孩子结点的值
将堆顶的元素保留起来,放在合理的位置
只要堆始终被维护这,那我们就一直可以获得堆中的最值
依次来进行排序
堆排序的时间复杂度为O(N*logN)

二、使用方法

1.利用现有的堆保存堆顶的数据

代码如下(示例):



void HeapSort(int* a, int n)
{
    //在有现成的堆的情况
    //把数组导入堆中去
    //把pop堆顶出来的元素存到a里面
    
    HeapInit(&hp);
    
    for (int i = 0; i < n; i++)
    {
        //插入元素
        HeapPush(&hp, a[i]);
    }

    //将堆里面的数据再重新拷贝回数组中
    for (int i = 0; i < n; i++)
    {
        a[i] = HeapTop(&hp);
        HeapPop(&hp);
    }

//以下是建堆时需要的自定义函数
//堆的初始化
void HeapInit(Heap* hp)
{
    hp->_capacity = 4;
    hp->_size = 0;
    HPDataType* tmp = (HPDataType*)malloc(sizeof(HPDataType) * 4);
    if (!tmp)
    {
        perror("malloc");
        return;
    }
    hp->_a = tmp;
}

// 堆的插入
void HeapPush(Heap* hp, HPDataType x)
{
    assert(hp);
    AdjustCapacity(hp);
    //第一步插入
    hp->_a[hp->_size] = x;
    hp->_size++;
    //第二步调整
    AdjustUp(hp->_a, hp->_size - 1);
}


// 堆的删除
void HeapPop(Heap* hp)
{
    assert(hp);
    assert(!HeapEmpty(hp));

    //交换首尾
    Swap(&hp->_a[0], &hp->_a[hp->_size - 1]);
    hp->_size--;
    //调整
    AdjustDown(hp->_a, hp->_size, 0);
}

// 取堆顶的数据
HPDataType HeapTop(Heap* hp)
{
    assert(hp);
    if (HeapEmpty(hp))
    {
        return -1;
    }
    return hp->_a[0];
}

2.把原有的数组调整为堆,将top元素放数组尾

代码如下(示例):

void HeapSort(int* a, int n)
{
    //当要调整的元素只剩一个时,就意味着调整完了
    while (n != 1)
    {
        //从最后一个叶子节点的父节点开始依次向下调整
        //调整顺序不断向上
        for (int i = (n - 1 - 1) / 2; i >= 0; i--)
        {
            AdjustDown(a, n, i);
        }
        Swap(&a[0], &a[n - 1]);
        n--;
    }
}
//以下是需要使用到的自定义函数
//交换两个元素
void Swap(HPDataType* a, HPDataType* b)
{
    HPDataType tmp = *a;
    *a = *b;
    *b = tmp;
}

//向下调整
void AdjustDown(int *a, int n, int parent)
{
    assert(a);
    int child = parent * 2 + 1;
    while (child < n)
    {
        if (a[child] > a[child + 1] && child + 1 < n)
        {
            child++;
        }

        if (a[child] < a[parent])
        {
            Swap(&a[parent], &a[child]);
            parent = child;
            child = parent * 2 + 1;
        }
        else
        {
            break;
        }

    }
}

总结

以上就是今天要讲的堆排序的内容,本文仅仅简单介绍了堆排序的使用,能够有效的解决排序速度慢的问题。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

CtrlZ大牛

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值