[排序算法]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)都要短,但由于要使用堆这个相对复杂的数据结构,所以实现起来也较为困难。

一般来说,需要排序的数据都存储在数组中。这次我们使用了堆这种数据结构,但实际上,这也相当于将堆嵌入到包含了序列的数组中,然后在数组中通过交换数据来进行排序。具体来说,就是让堆中的各结点和数组像下图这样呈对应关系。正如大家所见,这可以说是强行在数组中使用了堆结构。

代码演示

python 复制代码
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

相关推荐
_.Switch10 分钟前
Python机器学习模型的部署与维护:版本管理、监控与更新策略
开发语言·人工智能·python·算法·机器学习
zengy531 分钟前
Effective C++中文版学习记录(三)
数据结构·c++·学习·stl
自由的dream1 小时前
0-1背包问题
算法
2401_857297911 小时前
招联金融2025校招内推
java·前端·算法·金融·求职招聘
良月澪二3 小时前
CSP-S 2021 T1廊桥分配
算法·图论
wangyue44 小时前
c# 线性回归和多项式拟合
算法
&梧桐树夏4 小时前
【算法系列-链表】删除链表的倒数第N个结点
数据结构·算法·链表
QuantumStack4 小时前
【C++ 真题】B2037 奇偶数判断
数据结构·c++·算法
今天好像不上班4 小时前
软件验证与确认实验二-单元测试
测试工具·算法
wclass-zhengge5 小时前
数据结构篇(绪论)
java·数据结构·算法