从堆的建立到堆排序

前言

每个排序方法的速度都有各异,其中,堆排序算是顶流,速度相当的快,但也相对难理解点,这篇文章将想你讲解从堆的建立到堆排序

一、堆是什么?

堆就是一种特殊的队列

堆是由二叉树延伸出来的,而二叉树又是从顺序表(数组)转化过来的

数组本来就是数组,但是有大佬把数组想象成了二叉树,然后又接着在二叉树的基础上搞出了堆,堆就可以衍生出很多技巧和方法

二、建堆方法

1.向上建堆法

向上建堆法原理就是将要导入的数组依次插入到新的数组中,但是每插入一次都顺便向上调整一次

图解如下:
在这里插入图片描述

示例代码:

void UpAdjust(int* arr, int child)
{
    
    int parent = (child - 1) / 2;
    while (child > 0)
    {
        if (arr[child] > arr[parent])
        {
            Swap(&arr[child], &arr[parent]);
            child = parent;
            parent = (parent - 1) / 2;
        }
        else
        {
            break;
        }
    }
}

2.向下建堆法

向下建堆的原理就是可以将某棵已经建的差不多的树(只剩堆顶没调整)建成完整的堆,前提是这棵树下面就是堆(适合原地建堆)

图解如下:
在这里插入图片描述

示例代码:

//向下调整
void DownAdjust(int* arr, int size, int parent) //size为
{
    int child = parent * 2 + 1;

    while (child < size)
    {
        //找出两个孩子中最小的
        if (child + 1 < size && arr[child + 1] > arr[child])
        {
            child++;
        }

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

三、堆排序的方法

(建大堆为升序,建小堆为降序)
(前提是得先有堆)

换位法:

  • 将堆顶的数都放在最后面,已经放了的就不用管了
  • 一开始size个元素的堆,将堆顶元素和最后一个元素交换(最后一个元素不用再参与调整),然后这size-1个元素再调整出新的堆(向上或者向下建堆法都可以),再把堆顶元素和最后一个元素交换,直到size = 1;
  • 利用堆顶的元素为最值这一特点,将最值依次放到队尾,便达到了排序的作用

图解如下:

在这里插入图片描述

示例代码:

//堆排序
void HeapSort(int* arr, int size)
{
    assert(arr);
    assert(size != 0);
    //先建一次堆
    for (int i = 1; i < size; i++)
    {
        UpAdjust(arr, i);
    }
    //此时已经有最大的数了

    //利用向下调整法,将之后次大的数放到最后面
    while (size > 1)
    {
        //size就是数组的个数
        Swap(&arr[0], &arr[size - 1]);//arr[size - 1]就是数组最后一个元素
        //当最大的那个数已经被放到最后面的时候,要调整的个数就变成了size-1
        DownAdjust(arr, size - 1, 0);//向下调整中的size-1代表的是,你要调整的数据个数,并不是数组最后一个下标
        size--;
    }
}

总结

以上就是今天要讲的内容,本篇文章着重讲解了两个建堆方法以及堆排序的原理和思路,在力扣以及牛客网中还会有很多类似的题目,今后将会持续更新,敬请关注!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

CtrlZ大牛

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

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

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

打赏作者

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

抵扣说明:

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

余额充值