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

相关推荐
海洲探索-Hydrovo11 小时前
TTP Aether X 天通透传模块丨国产自主可控大数据双向通讯定位模组
网络·人工智能·科技·算法·信息与通信
_OP_CHEN12 小时前
C++基础:(十二)list类的基础使用
开发语言·数据结构·c++·stl·list类·list核心接口·list底层原理
2401_8414956414 小时前
【计算机视觉】基于复杂环境下的车牌识别
人工智能·python·算法·计算机视觉·去噪·车牌识别·字符识别
Jonkin-Ma14 小时前
每日算法(1)之单链表
算法
晚风残15 小时前
【C++ Primer】第六章:函数
开发语言·c++·算法·c++ primer
杨云强15 小时前
离散积分,相同表达式数组和公式
算法
地平线开发者15 小时前
征程 6 | BPU trace 简介与实操
算法·自动驾驶
满天星830357715 小时前
【C++】AVL树的模拟实现
开发语言·c++·算法·stl
Lris-KK16 小时前
力扣Hot100--94.二叉树的中序遍历、144.二叉树的前序遍历、145.二叉树的后序遍历
python·算法·leetcode
麦麦鸡腿堡16 小时前
Java的动态绑定机制(重要)
java·开发语言·算法