最大最小堆整理 & heapq最小最大堆

参考资料:
关于堆排序的算法参考:https://www.cnblogs.com/chengxiao/p/6129630.html
关于堆排序的视频演示:
https://www.bilibili.com/video/av18980178/
对于一个数组,可以使用min()和max()来求最大最小值而不是使用堆,但是根据python的wiki:https://wiki.python.org/moin/TimeComplexity
可以看到min()和max()的时间复杂度为O(N).
最大最小堆整理 & heapq最小最大堆_第1张图片
使用最大最小堆的好处:堆排序的插入时间复杂度为O(logN),得到最大最小值的时间复杂度为O(1)


python实现堆排序

参考:https://www.jianshu.com/p/e003872fa7b9

创建堆

创建堆有两种方式,heappush()和heapify()。
导入heapq库(python自带库)

import heapq
data = [1,5,3,2,8,5]
heap = []
for n in data:
    heapq.heappush(heap, n)
print(heap)
>>>> [1, 2, 3, 5, 8, 5]

或者

import heapq
data = [1,5,3,2,8,5]
heapq.heapify(data)
>>>> [1, 2, 3, 5, 8, 5]

可以看到两种堆是一样的,如果数据存在内存中,是不是使用heapify好一点

访问堆内容

最小堆使用data[0]即可访问最小元素

import heapq
data = [1,5,3,2,8,5]
heapq.heapify(data)
print(data)
print(data[0])
>>>> 
[1, 2, 3, 5, 8, 5]
1

使用heappop删除堆最小的元素

import heapq

data = [1,5,3,2,8,5]
heapq.heapify(data)
print(heapq.heappop(data))
print(data)
>>>>
1
[2, 5, 3, 5, 8]

可以看到删除了最小元素,调整之后仍然是最小堆,就是与根节点与叶子节点互换之后,删除叶子节点,继续调整位置。


删除最小元素,替换新的值heapreplace()

import heapq

data = [1,5,3,2,8,5]
heapq.heapify(data)
heapq.heapreplace(data, 10)
print(data)
>>>>
[2, 5, 3, 10, 8, 5]

若干个最大最小值

heapq还包括两个检查可迭代对象的函数,查找其中包含的最大值与最小值的范围

import heapq

data = [1,5,3,2,8,5]
print heapq.nlargest(3, data)
print heapq.nsmallest(3, data)
>>>>
[8, 5, 5]
[1, 2, 3]

heapq最大堆

heapq支持最大堆

import heapq

data = [1,5,3,2,8,5]
heapq._heapify_max(data)
print(data)
print(heapq._heappop_max(data))
print(data)
heapq._heapreplace_max(data, 12)
print(data)
>>>>
[8, 5, 5, 2, 1, 3]
8
[5, 5, 3, 2, 1]
[12, 5, 3, 2, 1]

可以看到,支持最大堆,但是有一个问题,如下面代码

import heapq

data = [1,5,3,2,8,5]
heapq._heapify_max(data)
print(data)
print(heapq._heappop_max(data))
print(data)
heapq._heapreplace_max(data, 12)
print(data)
heapq.heappush(data, 15)
print(data)
>>>>

[8, 5, 5, 2, 1, 3]
8
[5, 5, 3, 2, 1]
[12, 5, 3, 2, 1]
[12, 5, 3, 2, 1, 15]
12

可以看到,往heapq不支持maxpush,也就是说往里面push一个15,得到的堆并不是最大堆,在Stack Overflow上面有解答https://stackoverflow.com/questions/2501457/what-do-i-use-for-a-max-heap-implementation-in-python

The easiest way is to invert the value of the keys and use heapq. For example, turn 1000.0 into -1000.0 and 5.0 into -5.0.

也就是将负数转化为整数插入到最小堆,每次输入输出的时候都取相反数,但是当负数和正数同时存在的时候,就会有问题。
当然也可用再使用O(logN)来创造最大堆
反正也需要O(logN)的时间复杂度

heapq._heapify_max(data)

你可能感兴趣的:(基础算法)