python 堆排序
堆排序是对选择排序的一种优化算法,都属于选择排序类。
基本过程:堆是一种完全二叉树,是一种树形选择结构,将待排序的序列构造成一个大顶堆(即每个节点的值都大于或等于其左右孩子节点的值),然后将堆顶的根节点移走,与堆数组的末尾元素交换,此时末尾元素就是最大值。再将剩余的n-1个序列重新构造一个堆,得到次大值置于末尾,反复执行得到一个有序序列。
过程可参考如下图:
这里需要注意的,堆排序为了方便完全二叉树的计数,序列的首位置为空,忽略不计。
示例代码如下:
def heap_sort(lst): n = len(lst)-1 # 这里注意根据python的range列表的性质,要将序列长度减一,否则列表长度溢出 for i in range(n/2, 0, -1): heap_adjust(lst, i, len(lst)) while n > 1: lst[1], lst[n] = lst[n], lst[1] # 将堆顶记录和当前未经排序子序列的最后一个记录交换 heap_adjust(lst, 1, n) # 将lst[n]重新调整为大顶堆 n -= 1 return lst[1:] # 这里为了方便完全二叉树的计数,将序列中的首个元素置为空忽略不计 def heap_adjust(lst, k, size): # 自顶向下堆化,从k开始堆化 N = size - 1 while 2 * k <= N: lchild = 2 * k rchild = 2 * k + 1 if lchild < N and lst[lchild] < lst[rchild]: # 选出左右孩子节点中更大的那个,并将关键字赋值给左孩子 lchild = rchild if lst[k] < lst[lchild]: # 将左孩子与父节点比较,选出大的 lst[k], lst[lchild] = lst[lchild], lst[k] k = lchild # 将k扩倍,对孙节点排序 else: break if __name__ == "__main__": start = time.clock() rand_lst = [] for i in range(10): rand_lst.append(round(random.random()*100, 2)) lst = heap_sort(rand_lst) end = time.clock() print lst print "done ", (end-start)
性能方面:
堆排序的运行时间主要消耗在初始构建堆和重建堆的反复筛选上。
由于堆排序对原始记录的排序状态并不敏感,因此它无论是最好、最坏和平均时间复杂度都为O(nlogn),空间复杂度上它只有一个用来交换的暂存单元,所以为O(1),但是由于记录的比较和交换是跳跃进行的,所以堆排序是不稳定的排序方法。此外,由于它的性能主要消耗在堆的创建与重建上,所以不适合排序序列少的情况。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构