堆排序及代码实现

本文详细介绍了堆排序算法的工作原理,包括大顶堆和小顶堆的概念,以及如何通过最大堆调整、创建最大堆和堆排序过程来实现排序。堆排序的时间复杂度为Ο(nlogn),适合大规模数据的排序。文中还给出了Python实现堆排序的代码示例,展示了从无序数组构建最大堆并进行排序的过程。
摘要由CSDN通过智能技术生成

排序算法总结:

  1. 快速排序
  2. 堆排序
  3. 选择排序
  4. 希尔排序
  5. 冒泡排序
  6. 计数排序
  7. 桶排序
  8. 基数排序
  9. 插入排序
  10. 归并排序

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

  1. 大顶堆:每个节点的值都大于或等于其子节点的值,在堆排序算法中用于升序排列;
  2. 小顶堆:每个节点的值都小于或等于其子节点的值,在堆排序算法中用于降序排列;

堆排序的平均时间复杂度为 Ο(nlogn)。

一般用数组来表示堆,下标为 i 的结点的父结点下标为(i-1)/2;其左右子结点分别为 (2i + 1)、(2i + 2)
在这里插入图片描述
在堆的数据结构中,堆中的最大值总是位于根节点(在优先队列中使用堆的话堆中的最小值位于根节点)。堆中定义以下几种操作:

① 最大堆调整(Max_Heapify):将堆的末端子节点作调整,使得子节点永远小于父节点
② 创建最大堆(Build_Max_Heap):将堆所有数据重新排序
③ 堆排序(HeapSort):移除位在第一个数据的根节点,并做最大堆调整的递归运算

在堆排序的时候,对于一个无序数组,首先是从最后一个分支开始,依次创建最大堆,根据刚才说的父节点与左右子节点在数组中的索引关系,那对于数组的最后一个节点,其父节点就是length//2-1,例如一个长度为7的数组[1,2,3,4,5,6,7],二叉树如下:
在这里插入图片描述
最后一个节点7的父节点的值为3,索引为2.
最开始调整的最小子树就是3 6 7这个部分,调整好后节点3与7互换,得到7 6 3,父节点向前移动一位,继续调整2 4 5这个节点,
在这里插入图片描述

直到父节点来到根节点并且调整完毕,这时根节点为最大值:
在这里插入图片描述
但是在调整过程中,下面子树可能会再次不满足最大堆的条件,例如上树中,1 6 3这个子树就变的又不是最大堆了,所以在调整时,要时刻关注交换后是否会对下面的子树造成影响,做法是定一个标志点flag,当其为0时,表示当前子树满足最大堆,没有调整;当其为1时,表示父节点和左孩子发生了交换,那此时就要顺着左孩子继续向下找,再次调整其为最大堆;当其为2时,表明父节点和右子树发生了交换,这时要顺着右子树向下找,再次调整右子树为最大堆。

最大堆创建好后,其根节点就是最大值,这时将根节点与最后一个节点交换,根节点就来到了数组的最后。交换后,固定最后一个值,再次调整前面为最大堆,然后再次交换,直到整个数组有序。
在这里插入图片描述

Python实现:

def heapSort(arr):
    length = len(arr)
    if length <= 1:
        return

    i = length//2-1
    while i>=0:
        # 构造最大堆
        p, l, r = i, 2*i+1, 2*i+2
        flag = creatMaxHeap(arr, length, p, l, r)
        # 调整最大堆
        if flag == 1:
            adjustMaxHeap(arr, length, l)
        elif flag == 2:
            adjustMaxHeap(arr, length, r)
        i -= 1  
        
    # 排序
    end = length-1
    while end >= 1:
        arr[0], arr[end] = arr[end], arr[0] 
        p, l, r = 0, 1, 2
        flag = creatMaxHeap(arr, end, p, l, r)
        if flag == 1:
            adjustMaxHeap(arr, end, l)
        elif flag == 2:
            adjustMaxHeap(arr, end, r)
        end -= 1
     
    
def creatMaxHeap(arr, length, p, l, r):
    flag = 0
    if r<length:
        if arr[l] >= arr[r]:
            if arr[l] > arr[p]:
                arr[p], arr[l] = arr[l], arr[p]
                flag = 1
        else:
            if arr[r] > arr[p]:
                arr[p], arr[r] = arr[r], arr[p]
                flag = 2
    elif l<length:
        if arr[p] < arr[l]:
            arr[p], arr[l] = arr[l], arr[p]
            flag = 1
    return flag
    
def adjustMaxHeap(arr, length, p):
    l, r = 2*p+1, 2*p+2
    while r<length:
        flag = creatMaxHeap(arr, length, p, l ,r)
        if flag == 1: p = l
        elif flag == 2: p = r
        else:break
        l, r = 2*p+1, 2*p+2
    if l < length:
        if arr[l] > arr[p]:
            arr[l], arr[p] = arr[p], arr[l]



arr = [47, 29, 71, 99, 78, 19, 24]
heapSort(arr)
print(arr)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值