堆排序

堆排序

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

大顶堆:arr[i] >= arr[2i+1] && arr[i] >= arr[2i+2]  根节点大于两个子节点的值
小顶堆:arr[i] <= arr[2i+1] && arr[i] <= arr[2i+2]  根节点小于两个子节点的值

堆排序的基本思想是:将待排序序列构造成一个大顶堆,此时,整个序列的最大值就是堆顶的根节点。
    --> 有两个构造堆的过程:一个是初始数组构造成堆(不断从后面插入),另一个是堆顶与末尾元素互换后重新构造堆(从头向下比较)
将其与末尾元素进行交换,此时末尾就为最大值。然后将剩余n-1个元素重新构造成一个堆,这样会得到n个元素的次小值。
如此反复执行,便能得到一个有序序列了

1.首先将待排序的数组构造成一个大根堆,此时,整个数组的最大值就是堆结构的顶端
2.将顶端的数与末尾的数交换,此时,末尾的数为最大值,剩余待排序数组个数为n-1
3.将剩余的n-1个数再构造成大根堆,再将顶端数与n-1位置的数交换,如此反复执行,直到只剩下一个元素为止,便能得到有序数组
"""


# 将初始数组构造成大根堆(通过新插入的数上升)
def heapInsert(arr):
    """将待排序数组构造成一个大根堆,每次插入新的数据的时候,都与它的父节点进行比较,
       如果比父节点的值大,则进行交换,然后继续与新的父节点进行比较,直到小于等于父节点,或者到达顶端;
       如果比父节点小,则插入就可以了
    """
    for i in range(len(arr)):  # 遍历数组
        currentIndex = i    # 记录当前索引
        # 计算父节点
        fatherIdx = int((currentIndex - 1) / 2)
        # 当前节点与父节点的值进行比较
        while arr[currentIndex] > arr[fatherIdx]:  # 当前值比父节点大
            # 进行交换
            arr[currentIndex],arr[fatherIdx] = arr[fatherIdx],arr[currentIndex]
            # 更改当前的索引
            currentIndex = fatherIdx
            # 重新计算父节点
            fatherIdx = int((currentIndex - 1) / 2)
        # 直到当前节点到达顶端或者比父节点小,插入下一个


# 固定最大值,将剩余的数再次构造成大根堆,这属于一个循环操作,可以使用递归实现,直到只剩下一个元素结束
def heapify(arr,index,size):
    """将顶端的最大值与数组末尾的数交换,重新构造大根堆,通过顶端的数下降来重新构造"""
    # 计算当前index的左右子节点,index总是从根节点0开始
    left = 2 * index + 1
    right = 2 * index + 2
    while left < size:      # 当存在左孩子的时候,可以进行重新构造
        # 拿到子节点中较大值的索引
        largeIdx = 0
        if arr[left] < arr[right] and right < size:     # 右孩子存在并且右孩子大于左孩子,右子节点的索引值不能超过数组长度size(说明右孩子存在)
            largeIdx = right
        else:       # 没有右孩子或者左孩子值较大
            largeIdx = left

        # 如果当前父节点的值比较大孩子节点大,当前父节点,说明只有当前这个父节点的子树发生了变化
        if arr[index] > arr[largeIdx]:      # 当父节点已经是最大,说明已经构成大根堆
            break
        else:   # 继续修改当前父节点的子树
            # 如果父节点的值比孩子节点小,进行交换
            arr[index],arr[largeIdx] = arr[largeIdx],arr[index]
            # 更改父节点的索引指向
            index = largeIdx
            # 继续与新的子节点进行比较
            left = 2 * index + 1
            right = 2 * index + 2


# 进行堆排序
def heapSort(arr):
    # 构造大根堆
    heapInsert(arr)
    size = len(arr)
    # 固定最大值,再次构造大根堆
    while size > 1:
        arr[0],arr[size-1] = arr[size - 1],arr[0]   # 最大值与末尾元素交换
        size = size - 1     # 元素长度少了最大值
        heapify(arr,0,size)     # 重新构造大根堆
    return arr

if __name__ == '__main__':
    a = [1,5,7,4,12,36,48,1,2,4,78,89,6,100]
    print(heapSort(a))

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值