堆排序(Python)

排序算法平均时间复杂度空间复杂度稳定性
冒泡排序 O ( n 2 ) O(n^2) O(n2) O ( 1 ) O(1) O(1)稳定
选择排序 O ( n 2 ) O(n^2) O(n2) O ( 1 ) O(1) O(1)不稳定
插入排序 O ( n 2 ) O(n^2) O(n2) O ( 1 ) O(1) O(1)稳定
希尔排序 O ( n log ⁡ 2 n ) O(n\log^2 n) O(nlog2n) O ( 1 ) O(1) O(1)不稳定
归并排序 O ( n log ⁡ 2 n ) O(n\log^2 n) O(nlog2n) O ( n ) O(n) O(n)稳定
快速排序 O ( n log ⁡ n ) O(n\log n) O(nlogn) O ( log ⁡ n ) O(\log n) O(logn)不稳定
堆排序 O ( n log ⁡ n ) O(n\log n) O(nlogn) O ( 1 ) O(1) O(1)不稳定
计数排序 O ( n + k ) O(n+k) O(n+k) O ( k ) O(k) O(k)稳定
基数排序 O ( n × k ) O(n\times k) O(n×k)稳定
桶排序 O ( n ) O(n) O(n) O ( m ) O(m) O(m)稳定

堆排序使用一种被称为堆的数据结构进行排序。

(二叉)堆是一个数组,它可以被看成一个近似的完全二叉树。树上的每一个结点对应数组中的一个元素。除了最底层外,该树是完全充满的,而且从左向右填充。二叉堆可以分为两种形式:大顶堆和小顶堆在这里插入图片描述
大顶堆:每个结点的值都大于或等于其左右孩子结点的值,堆中最大的元素存放在根节点。
小顶堆:每个结点的值都小于或等于其左右孩子结点的值,堆中最小的元素存放在根节点。

由于堆是一个数组,对于大顶堆它的实际存储为:
在这里插入图片描述
给定堆中的一结点下标为 i,则其左孩子和右孩子对应下标分别为 2i+1 和 2i+2,若数组下标自 1 开始,则其左孩子和右孩子对应下标分别为 2i 和 2i+1。

堆排序算法(以大顶堆为例)

将待排序序列构造成一个大顶堆,此时,整个序列的最大值就是堆顶的根节点。将其与末尾元素进行交换,此时末尾就为最大值。然后将剩余 n-1 个元素重新构造成一个堆,这样会得到 n 个元素的次小值。如此反复执行,便能得到一个有序序列了

维护堆性质的函数

整个排序算法都建立在待排序列为大顶堆的基础上,而在根结点与末尾元素进行交换时会破坏大顶堆结构,需要有对大顶堆进行维护的函数。

在该函数中给出根节点下标 root,根据堆的性质得到其左右孩子结点下标,选出三个结点的最大值,并将最大值下标赋给 max。若 root 为最大结点,以 root 为根节点的子树已经是最大堆,程序结束。否则,最大值是 root 的某个孩子结点,交换 max 结点同 root 结点的值。由于 root 结点的一个孩子结点值发生改变,以该孩子结点为根的子树可能违反最大堆性质,递归调用函数。

def max_heapify(arr, root):
    max_, left, right = root, 2 * root + 1, 2 * root + 2
    # 全局变量 arr_len
    if left < arr_len and arr[left] > arr[max_]:
        max_ = left
    if right < arr_len and arr[right] > arr[max_]:
        max_ = right
    
    if max_ != root:
        arr[root], arr[max_] = arr[max_], arr[root]
        max_heapify(arr, max_)

建堆函数

想要进行堆排序,首先需要将初始序列变成大顶堆
我们可以用自底向上的方法利用函数 max_heapify() 将一个初始序列变成大顶堆

def build_max_heap(arr):
    # 叶子节点无需维护堆性质
    # 不需遍历整个数组
    for i in range(len(arr) // 2,-1,-1):
        max_heapify(arr,i)

排序函数

将大顶堆根节点与末尾元素进行交换,此时末尾就为最大值。然后将剩余 n-1 个元素重新构造成一个堆,这样会得到 n 个元素的次小值。如此反复执行,便能得到一个有序序列了

def heap_sort(arr):
    global arr_len
    arr_len = len(arr)
    if arr_len < 2:
        return arr
    
    build_max_heap(arr)
    for i in range(len(arr) - 1, 0, -1):
        arr[0], arr[i] = arr[i], arr[0]
        arr_len -= 1
        max_heapify(arr, 0)

知识来源

<<算法导论>>第6章堆排序
图片直接从这位大大这拿图并参考https://www.cnblogs.com/chengxiao/p/6129630.html


本博客文章仅供博主学习交流,博主才疏学浅,语言表达能力有限,对知识的理解、编写代码能力都有很多不足,希望各路大神多多包涵,多加指点。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值