[排序算法]4. 图解堆排序及其代码实现

先来看看什么是堆?           

        堆是一种图的树形结构,被用于实现“优先队列”(priority queues)

注:优先队列是一种数据结构,可以自由添加数据,但取出数据时要从最小值开始按顺序取出。

        在堆的树形结构中,各个顶点被称为“结点”(node),数据就存储在这些结点中,堆中的每个结点最多有两个子结点

        在堆中存储数据时必须遵守这样一条规则:子结点必定大于父结点。因此,最小值被存储在顶端的根结点中。从堆中取出数据时,取出的是最上面的数据。这样,堆中就能始终保持最上面的数据最小。同时由于最上面的数据被取出,因此堆的结构也需要重新调整。


01 首先,在堆中存储所有的数据,并按降序来构建堆。


02 现在,所有数据都存进堆里了。为了排序,需要再从堆中把数据一个个取出来。

注:
从降序排列的堆中取出数据时会从最大的数据开始取,所以将取出的数据反序输出,排序就完成了。


03 首先取出根结点的数字7。


04 重新构造堆。

重构的规则请参考:

[数据结构]图解堆结构及其代码实现-CSDN博客

05 同样地,取出根结点的数字6,将它放在右数第2个位置上。


06 重新构造堆。


07 重复上述操作直到堆变空为止。


08 排序中……


09 从堆中取出了所有数字,排序完成。

解说
        堆排序一开始需要将n个数据存进堆里,所需时间为O(nlogn)。排序过程中,堆从空堆的状态开始,逐渐被数据填满。由于堆的高度小于log2n,所以插入1个数据所需要的时间为O(logn)。
每轮取出最大的数据并重构堆所需要的时间为O(logn)。由于总共有n轮,所以重构后排序的时间也是O(nlogn)。因此,整体来看堆排序的时间复杂度为O(nlogn)。
        这样来看,堆排序的运行时间比之前讲到的冒泡排序、选择排序、插入排序的时间O(n2)都要短,但由于要使用堆这个相对复杂的数据结构,所以实现起来也较为困难。
        一般来说,需要排序的数据都存储在数组中。这次我们使用了堆这种数据结构,但实际上,这也相当于将堆嵌入到包含了序列的数组中,然后在数组中通过交换数据来进行排序。具体来说,就是让堆中的各结点和数组像下图这样呈对应关系。正如大家所见,这可以说是强行在数组中使用了堆结构。

 

代码演示

def heapify(arr, n, i):
    # 初始化最大值的索引为当前节点
    largest = i
    # 左子节点的索引
    left = 2 * i + 1
    # 右子节点的索引
    right = 2 * i + 2

    # 如果左子节点比当前节点大,更新最大值索引
    if left < n and arr[i] < arr[left]:
        largest = left

    # 如果右子节点比当前节点大,更新最大值索引
    if right < n and arr[largest] < arr[right]:
        largest = right

    # 如果最大值不是当前节点,交换值并递归调整
    if largest != i:
        arr[i], arr[largest] = arr[largest], arr[i]
        heapify(arr, n, largest)


def heap_sort(arr):
    n = len(arr)

    # 构建最大堆(Max Heap)
    # 从最后一个非叶子节点开始到根节点,逐个进行堆调整
    for i in range(n // 2 - 1, -1, -1):
        heapify(arr, n, i)

    # 逐步取出最大元素并进行堆调整
    for i in range(n - 1, 0, -1):
        # 将当前最大值(堆顶)与未排序部分的最后一个值交换
        arr[i], arr[0] = arr[0], arr[i]
        # 对剩余元素重新构建最大堆
        heapify(arr, i, 0)

    return arr


arr = [2, 6, 7,8, 9, 4, 10, 3, 5, 1]
sorted_arr = heap_sort(arr)
print(sorted_arr)
结果:
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

更详细的可以看这篇文章:

[数据结构]图解堆结构及其代码实现-CSDN博客


文章来源:书籍《我的第一本算法书》

书籍链接:

我的第一本算法书 (豆瓣) (douban.com)

作者:宫崎修一 石田保辉

出版社:人民邮电出版社

ISBN:9787115495242

本篇文章仅用于学习和研究目的,不会用于任何商业用途。引用书籍《我的第一本算法书》的内容旨在分享知识和启发思考,尊重原著作者宫崎修一和石田保辉的知识产权。如有侵权或者版权纠纷,请及时联系作者。
————————————————

                            版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
                        
原文链接:https://blog.csdn.net/jhghuhbb/article/details/139089141

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值