堆排序(Heap Sort)

1 概述

堆排序(Heapsort)是指利用堆这种数据结构所设计的一种排序算法。堆积是一个近似完全二叉树的结构,并同时满足堆积的性质:即子结点的键值或索引总是小于(或者大于)它的父节点。

2 算法流程

  1. 首先构建最大堆,要求是每个非叶节点的值大于其左右子节点的值,构建过程从非叶节点最大序号开始,根据【父节点是i,则其左子节点是2*i+1,其右子节点是2*i+2】的规律,进行检查,如果不满足则需要做交换
  2. 根据最大堆,将根节点的最大值与末尾叶节点交换,将最大值取出,实质上是选择过程,然后重新检查堆,调整为最大堆
  3. 循环步骤2,直至取出序列中所有的值

3 代码/Python

def buildMaxHeap(arr):
    import math
    # 最大堆构建过程,主要需要检查所有父节点是否大于子节点
    # 二叉树的非叶节点最大序号只能是floor(len(arr)/2),降序检查
    for i in range(math.floor(len(arr)/2),-1,-1): 
        heapify(arr,i)

def heapify(arr, i):
    # 设定最大节点是父节点    
    largest = i 
    # 对应的两个子节点(可能不存在)
    left = 2*i+1 
    right = 2*i+2 
    # 如果子节点大于父节点,则需要交换
    if left < arrLen and arr[left] > arr[largest]:
        largest = left
    if right < arrLen and arr[right] > arr[largest]:
        largest = right
    if largest != i:
        swap(arr, i, largest)
        # 交换之后要检查被交换的节点作为父节点是否满足最大堆要求
        heapify(arr, largest)

def swap(arr, i, j):
    arr[i], arr[j] = arr[j], arr[i]

def heapSort(arr):
    global arrLen
    arrLen = len(arr)
    buildMaxHeap(arr) # 构建最大堆
    for i in range(len(arr)-1,0,-1):
        # 每次循环将最大值交换到最后位置
        swap(arr,0,i)
        arrLen -=1
        # 检查根节点是否满足最大堆要求
        heapify(arr, 0)
    return arr

# 算法调用
import random
nums = [random.randint(0,100) for i in range(10)]

print('随机生成10个数字:', nums)
print('排序后输出结果为:', heapSort(nums))

4 算法解释

  • 堆排序是利用完全二叉树性质,进行数值交换和最大值选择
  • 时间复杂度:构建初始堆经推导复杂度为 O ( n ) O(n) O(n),在交换并重建堆的过程中,需交换n-1次,而重建堆的过程中,根据完全二叉树的性质, [ log ⁡ 2 ( n − 1 ) , log ⁡ 2 ( n − 2 ) . . . , 1 ] [\log_2(n-1),\log_2(n-2)...,1] [log2(n1),log2(n2)...,1]逐步递减,近似为) n log ⁡ n n\log n nlogn。所以堆排序时间复杂度一般认为就是 O ( n log ⁡ n ) O(n\log n) O(nlogn)级。,因此最坏,最好,平均时间复杂度均为 O ( n l o g n ) O(nlogn) O(nlogn)
  • 空间复杂度:由于堆排序是原地进行交换,所以空间复杂度是 O ( 1 ) O(1) O(1)
  • 稳定性:在排序过程,需要大范围替换元素,存在相等元素替换之后顺序颠倒,所以是不稳定的
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值