关于heapq(优先级队列算法):
heapq.heapify(x):个人理解就是以线性时间(O(n)时间)将一个list转换经过堆排序之后在放入list中,而这种堆特点是根节点必须小于左右节点。曾听到过一个说法,在java里面这种叫堆排序方法做小根堆
例子:
>>> import heapq
>>> list1 = [1,4,7,2,6,23,56,3,7]
>>> heapq.heapify(list1)
>>> list1
[1, 2, 7, 3, 6, 23, 56, 4, 7]
图如下:
heapq.heappush(heap, item) # 将新的值经过堆排序放入到list中
>>> list1
[]
>>> heapq.heappush(list1, 1) # 插入堆
>>> heapq.heappush(list1, 6)
>>> heapq.heappush(list1, 8)
>>> heapq.heappush(list1, 2)
>>> heapq.heappush(list1, 3)
>>> list1
[1, 2, 8, 6, 3]
heapq.heappop(heap) # 弹出经过堆排序之后list中最小值
>>> heapq.heappop(list1) # list1为heapq.heappush()中的list1
1
heapq.heappushpop(heap,item) # 插入一个数,将其按照规则排好再弹出最小值
>>> heapq.heappushpop(list1, 2) # 如果插入的是最小值,那么弹出的会是自己
2
>>> heapq.heappushpop(list1, 4)
3
>>> list1
[4, 6, 8]
heapq.heapreplace(heap,item) # 这个与heappushpop原理有点不同,是先将最小的值弹出来,再新插入的数据放到原来堆排序排好的list中弹出的位置再进行按堆排序规则排序(纯属个人理解,有误请指出,在此多谢)
>>> list1 = [1,3,5,7,9]
>>> heapq.heapreplace(list1, 8)
1
>>> list1
[3, 7, 5, 8, 9]
heapq.nlargest(n,iterable,key=None) # 返回经过堆排序中list最大的n个值
>>> list1 = [1,3,5,7,9]
>>> heapq.nlargest(2, list1)
[9, 7]
>>> list1 = {1:8, 2:7, 3:6}
>>> heapq.nlargest(2, list1, key=lambda x: list1[x]) # 可以使用key来选择判断依据
[1, 2]
heapq.nsmallest(n, iterable, key=None) # 与nlargest相反
>>> list1 = [1,3,5,7,9]
>>> heapq.nsmallest(2, list1)
[1, 3]
>>> list1 = {1:8, 2:7, 3:6}
>>> heapq.nsmallest(2, list1, key=lambda x: list1[x])
[3, 2]
heapq.merge(*iterables,key=None,reverse=False) # 合并两个经过堆排序的list
"""
该注释部分纯属个人理解,由于找不到构建heapq.merge的源码,所以无法真正得出结论,如果哪位大佬可以找到开源的heapq.merge函数可以分享一下
正如下图:(在此定义最小值为1的list为list1,最小值为2的list为list2)
当执行heapq.merge()函数合并时,list1和list2会将根节点(最小值)进行比较,取最小值那个当做合并后的根节点(最小值),当list1弹出最小值后,会将list1新的最小值与刚才未弹出list(list2)最小值再进行比较,以此循环进行比较构建新的经过堆排序的list
正如图片那样,如果有list1的最小值等于list2最小值该如何解决呢?
答:会先执行list1在heapq.merge()中的参数位置比list2靠前。所以本例子的两个76进行比较时,会弹出list1中的76放进新合并的list中
"""
>>> list1 = [1, 3, 4, 5, 76, 8]
>>> list2 = [2, 2, 6, 5, 23, 76, 9, 10]
>>> cheap = heapq.merge(list1, list2)
>>> for i in cheap:
... print(i)
...
1
2
2
3
4
5
6
5
23
76
8
76
9
10