python实现堆排序

本文深入解析了堆排序算法,包括最大堆和最小堆的概念,堆的自我调整机制,以及如何通过构建堆来实现排序。详细介绍了堆排序的Python代码实现,以及其时间复杂度。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

堆排序

概念:

二叉堆,二叉堆本质上是一种完全二叉树,可以分为最大堆和最小堆两种。最大堆:任何一个父节点的值都大于等于其子节点的值;最小堆:任何一个父节点的值都小于等于其子节点的值。
二叉堆的根节点叫堆顶,二叉堆的特点决定了最大堆的堆顶是整个堆数据中的最大值,最小堆的堆顶是整个堆数据中的最小值。

堆的自我调整:

插入节点:首先将节点插入到堆尾,然后判断新插入的节点与其父节点是否满足最大/小堆的概念,若不满足,则将节点上移,然后再检查是否满足条件,直至整个二叉堆均满足条件。
删除节点:
例如删除最小堆的堆顶,即删除堆数据中最小的数字,首先将堆顶1和堆尾10交换位置,然后删除新的堆尾1,并对堆顶10做向下调整,直至形成新的堆。10在做向下调整时应从左右子树中选取值最小的
在这里插入图片描述

构建二叉堆:

即将一颗无序的二叉树调整为最大/最小堆,下面主要介绍自下而上的构建二叉堆:本质上是让所有非叶子节点依次下沉。
在这里插入图片描述

堆的存储:

二叉堆在存储时,采用顺序存储的方式,对于节点n,其左右子节点为2n+1/2n+2,其父节点为(n-1)/2并向下取整。
在这里插入图片描述

堆排序:

首先构建最大/小堆,然后将堆顶元素移动到堆尾,并从最大/小堆中取出此数据,然后经过调整第二大/小的元素就会成为新的堆顶,不断重复此过程,堆中的数据会按顺序依次取出。
在这里插入图片描述

python代码实现堆排序:
#堆排序
def heap_sort(nums):
    build_heap(nums)
    for i in range(len(nums)-1,-1,-1):
        nums[0], nums[i] = nums[i], nums[0]
        max_heapify(nums, 0, i)

#构建堆
def build_heap(nums):
    lenght = len(nums)
    for i in range((lenght-1)//2,-1,-1):
        max_heapify(nums, i, lenght)

#将堆的节点向上调整
def max_heapify(nums, i, lenght):#i父节点的位置,length数组长度
    #找到节点的左右孩子节点
    left = i*2+1
    right = i*2+2
    #判断左右孩子节点与父节点的大小
    if left < lenght and nums[left] > nums[i]:
        largest = left
    else:
        largest = i
    if right < lenght and nums[right] > nums[largest]:
        largest = right
    if largest != i:
        nums[i], nums[largest] = nums[largest], nums[i]
        #调整子树
        max_heapify(nums, largest, lenght)

nums = [7,0,0,2,4,3]
if __name__ == "__main__":
    heap_sort(nums)
    print(nums)

#输出[0, 0, 2, 3, 4, 7]

堆排序的时间复杂度为O(nlog(n))。

### Python 实现堆排序算法示例 堆排序是一种基于二叉堆数据结构的比较型排序算法。该算法分为两步:构建最大堆和逐步交换根节点与最后一个元素并重新调整堆。 #### 构建最大堆 为了使数组满足最大堆的性质,即父节点总是大于等于子节点,可以使用 `heapify` 函数来维护这一特性: ```python def heapify(arr, n, i): largest = i # Initialize largest as root left = 2 * i + 1 # left child index right = 2 * i + 2 # right child index # Check if left child exists and is greater than root if left < n and arr[i] < arr[left]: largest = left # Check if right child exists and is greater than the current largest if right < n and arr[largest] < arr[right]: largest = right # Change root if needed if largest != i: arr[i], arr[largest] = arr[largest], arr[i] # Swap elements[^4] # Heapify the affected sub-tree recursively heapify(arr, n, largest) ``` #### 执行堆排序 完成最大堆之后,可以通过不断移除位于顶端的最大元素,并将其放置到最终位置上;随后减少考虑范围直至整个序列有序化: ```python def heap_sort(arr): n = len(arr) # Build a maxheap. for i in range(n // 2 - 1, -1, -1): heapify(arr, n, i) # One by one extract elements from heap for i in range(n-1, 0, -1): arr[i], arr[0] = arr[0], arr[i] # swap heapify(arr, i, 0) return arr ``` 上述代码展示了完整的堆排序过程,其中包含了创建初始大顶堆以及后续迭代过程中保持堆特性的方法[^5]。 #### 测试实例 这里给出一个简单的测试例子验证实现效果: ```python if __name__ == "__main__": test_array = [12, 11, 13, 5, 6, 7] print("原始数组:", test_array) sorted_array = heap_sort(test_array.copy()) print("排序后的数组:", sorted_array) # 输出应为已排序的结果 ``` 运行此程序将会得到如下输出: ``` 原始数组: [12, 11, 13, 5, 6, 7] 排序后的数组: [5, 6, 7, 11, 12, 13] ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值