排序算法:堆排序(C实现)

基本思想

堆排序(Heapsort)是指利用堆积树(堆)这种数据结构所设计的一种排序算法,它是选择排序的一种。它是通过堆来进行选择数据。需要注意的是排升序要建大堆,排降序建小堆

过程分析

在这里插入图片描述
我们先将上面的数字按照堆的形式展现出来:
在这里插入图片描述

  1. 以最后一棵小子树开始构建大堆,也就是下面蓝框选中的部分
    在这里插入图片描述
    把31拿出来和子树比较,因为该树只有左子树,所以只需要和左子树进行比较,发现1比31小,所以无需交换,然后换至下一棵树。

  2. 因为是倒叙构建才能不断把数字大的往上浮,所以下一棵树是以3号下标为根的子树,也就是下面蓝框选中的部分。
    在这里插入图片描述
    把45拿出来和下面的子树进行比较,左子树是5,右子树是47,比较大的是47,我们用47和45进行比较,发现3号下标的右子树大于该数字,所以47放到3号下标,45放到以8号为根的子树中去找自己的定位,因为8号下标已经没有子树了,所以就只能将45放到8号位置。
    在这里插入图片描述

  3. 下来我们该以2号下标为根的树了,比较完成后没有改变
    在这里插入图片描述

  4. 下来继续根为1号下标的树
    在这里插入图片描述
    因为47和31较大的是47,我们用47和3进行比较 ,47比3大,所以把47放到1号下标的位置,现在的状态是这样的。
    在这里插入图片描述
    本来3是要放在3号下标的,但是因为3号下标下面还有子树,所以不能放到3号下标,继续进行比较,5和45大的是45,45和3比较,45大,所以把45放到3号位置。
    在这里插入图片描述
    temp继续向下比较,8号位置没有子树了,所以就把3放到8号位置
    在这里插入图片描述
    这样以1号为根的树就完成了大堆的构建,下来是0号,同理最终构建得出的大堆是
    在这里插入图片描述
    到这里,我们的大堆构建过程已经完成了。

  5. 通过大堆我们可以得到这些数字中的最大数字,也就是现在处于0号下标的47,我们把47和最后9号下标的1进行交换,这样我们就得到了排序的最后面的一个数字。
    在这里插入图片描述
    然后我们把9号位置屏蔽掉,在0号到8号里面再次构建大堆。

  6. 构建完我们就在这些数中又可以得到堆顶最大的数字,如下图
    在这里插入图片描述

  7. 这次我们继续吧最大的45扔到最后,也就是和8号位置的3进行交换,交换完是这样子的
    在这里插入图片描述

  8. 依次类推,这样就得到了有序的序列,也就排序完成了。

代码实现

void Swap(int* x, int* y)
{
    int tmp = *x;
    *x = *y;
    *y = tmp;
}

void AdJustDown(int* arr, int n, int root)
{
    int parent = root;
    int child = parent * 2 + 1;
    while (child < n)
    {
        if (child + 1 < n && arr[child] < arr[child + 1])
        {
            ++child;
        }

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

void HeapSort(int* arr, int n)
{
    //排升序,建大堆
    for (int i = (n - 1 - 1) / 2; i >= 0; --i)
    {
        AdJustDown(arr, n, i);
    }

    int end = n - 1;
    while (end > 0)
    {
        //把堆顶当前最大的数依次换到最后
        Swap(&arr[0], &arr[end]);
        AdJustDown(arr, end, 0);
        --end;
    }
}

测试用例:

void Test()
{
    int arr[] = { 4, 3, 15, 45, 31, 14, 9, 5, 47, 1 };
    int length = sizeof(arr) / sizeof(arr[0]);
    HeapSort(arr, length);
    for (int i = 0; i < length; i++)
    {
        printf("%d ", arr[i]);
    }
    printf("\n");
}

在这里插入图片描述

特性总结

  1. 堆排序使用堆来选数,效率就高了很多。
  2. 时间复杂度:O(N*logN)
  3. 空间复杂度:O(1)
  4. 稳定性:不稳定
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值