[排序算法]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

相关推荐
云卓SKYDROID1 分钟前
除草机器人算法以及技术详解!
算法·机器人·科普·高科技·云卓科技·算法技术
半盏茶香25 分钟前
【C语言】分支和循环详解(下)猜数字游戏
c语言·开发语言·c++·算法·游戏
徐子童29 分钟前
双指针算法习题解答
算法
想要打 Acm 的小周同学呀38 分钟前
LRU缓存算法
java·算法·缓存
劲夫学编程2 小时前
leetcode:杨辉三角
算法·leetcode·职场和发展
毕竟秋山澪2 小时前
孤岛的总面积(Dfs C#
算法·深度优先
浮生如梦_4 小时前
Halcon基于laws纹理特征的SVM分类
图像处理·人工智能·算法·支持向量机·计算机视觉·分类·视觉检测
励志成为嵌入式工程师6 小时前
c语言简单编程练习9
c语言·开发语言·算法·vim
捕鲸叉6 小时前
创建线程时传递参数给线程
开发语言·c++·算法
A charmer6 小时前
【C++】vector 类深度解析:探索动态数组的奥秘
开发语言·c++·算法