堆排序
1 python默认是小顶堆,想要实现大顶堆入堆的时候要添加负号,出堆的时候也添加负号,求前 k 大,用小根堆,求前 k 小,用大根堆,
python用heapq模块来实现小顶堆,它有六个函数,其中四个函数用的最多,一个是heapify()直接对数组进行堆化,两个是heappush() heappop()分别是对已经堆化的插入元素和删除元素,一个是heapqreaplce()删除堆顶元素再插入元素进行堆化,由heappush() heappop()也可以完成,
import heapq # 注意利用heappush的时候,它默认L是已经堆化的数组,所以必须从空数组开始插入, # 不堆化直接插入元素是错误的 L = [444,6,5,8,2] heapq.heappush(L, 1) print(L) # [1, 6, 444, 8, 2, 5] L = [] for i in [6,5,4,3,2]: # 这实际上是插入元素堆排序的方法, heapq.heappush(L, i) print(L) # [2, 3, 5, 6, 4] # heappop()弹出堆顶的元素 m = heapq.heappop(L) print(m, L) # heapify()直接对数组进行堆化, # 如果堆并不是使用heappush创建的,应在使用heappush和heappop之前使用这个函数进行堆化 L = [6,5,4,3,2] heapq.heapify(L) print(L) # [2, 3, 4, 6, 5] # 函数heapreplace用得没有其他函数那么多。它从堆中弹出最小的元素,再压入一个新元素。 # 相比于依次执行函数heappop和heappush,这个函数的效率更高。 heapq.heapreplace(L, 1) # 弹出堆顶的2,压入1,再堆化, print(L) # nlargest(n, iter)和nsmallest(n, iter),:分别用于找出可迭代对象iter中最大和最小的n个元素 # 直接输出最小的n个数或最大的n个数, print(heapq.nsmallest(3, L)) print(heapq.nlargest(3, L)) # [1, 3, 4] # [6, 5, 4]
参考:https://blog.csdn.net/jamfiy/article/details/88185512
https://www.cnblogs.com/cooffeeli/p/heapSort.html
https://blog.csdn.net/loveliuzz/article/details/77618530
2 堆排序代码
def heap_sort(list): # 创建最大堆, for start in range((len(list) - 2) // 2, -1, -1): sift_down(list, start, len(list) - 1) # 堆排序 for end in range(len(list) - 1, 0, -1): # 先把最大值放到数组的最后,再把第二大的数放到拿出来放到倒数第二个,再把第三大的数拿出来放到 # 倒数第三个,依次类推 list[0], list[end] = list[end], list[0] sift_down(list, 0, end - 1) return list # 最大堆调整 # 这个函数的作用是,每次把start索引的节点放到它该放的位置,如果它已经大于左右节点了,结束, # 否则不断下沉,注意这里的下沉范围是从start节点到end节点, def sift_down(lst, start, end): root = start while True: # 由根节点索引计算出左节点的索引 child = 2 * root + 1 # 如果左节点索引越界,结束 if child > end: break # 右节点索引未出界,且左节点的值小于右节点的值, # 这一步的目的是在左右节点中选出一个大的来,与根节点比较 if child + 1 <= end and lst[child] < lst[child + 1]: # 更新child为右节点 child += 1 # 如果大的子节点大于根节点时,则交换二者的值, # 并把根节点更新为子节点,继续最大堆 if lst[root] < lst[child]: lst[root], lst[child] = lst[child], lst[root] root = child else: break l = [8,12,9,30,1,3,4,5,23,6,7] print(heap_sort(l))
ttt