目录
堆的定义
堆满足以下特性:
堆的存储
heapq模块
创建堆:
heapq.heapify(li)
heapq.heappush(li, num)
heapq.heappop(li)
heapq.heappushpop(li, num)
heapq.heapreplace(li, num)
heapq.merge(li,li2)
heapq.nlargest(n, li, key=None)
heapq.nsmallest(n, li, key=None)
堆排序:
堆排序与快速排序,归并排序一样都是时间复杂度为O(N*logN)的几种常见排序方法。学习堆排序前,先讲解下什么是数据结构中的堆。
堆是完全二叉树或者是近似完全二叉树。
父结点的键值总是大于或等于(小于或等于)任何一个子节点的键值。
每个结点的左子树和右子树都是一个堆(都是最大堆或最小堆)。
当父结点的键值总是大于或等于任何一个子节点的键值时为最大堆。当父结点的键值总是小于或等于任何一个子节点的键值时为最小堆。而heapq模块就是以最小堆写的:
一般都用列表来表示堆,i结点的父结点下标就为(i – 1) / 2。它的左右子结点下标分别为2 * i + 1和2 * i + 2。如第0个结点左右子结点下标分别为1和2。
引用库的方法:import heapq;如果想省去前缀就使用from heapq import*
创建一个堆,可以使用list来初始化为 []
;也可以通过一个函数 heapify(),来把一个list转换成堆
heapq.
heapify
(li)将自身list 转换成堆,在线性时间内。
from heapq import*
li=[5,2,0,1,3,1,4]
heapify(li)
print(li)
输出:
[0, 1, 1, 2, 3, 5, 4]
heapq.
heappush
(li, num)将 num 的值加入 li 中,并保持堆不变
heappush(li,8)
print(li)
输出:
[0, 1, 1, 2, 3, 5, 4, 8]
heapq.
heappop
(li)弹出并返回 li 的最小的元素,保持堆的不变性。如果堆为空,抛出 indexError。
使用 heap[0]
,可以只访问最小的元素而不弹出它。
heappush(li,8)
print("pop前是{}".format(li[0]))
heappop(li)
print("pop后是{}".format(li[0]))
print(li)
输出:
输出前是0
pop后是1
[ 1, 1, 2, 3, 5, 4, 8]
heapq.
heappushpop
(li, num)将 num 放入堆中,然后弹出并返回 li 的最小元素。该组合操作比先调用 heappush()再调用 heappop()运行起来更有效率。
heappushpop(li,3)
print(li)
输出:
[1, 2, 4, 3, 3, 5, 8]
heapq.
heapreplace
(li, num)弹出并返回 li 中最小的一项,同时推入新的 num。 堆的大小不变。 如果堆为空则引发 indexError。
这个单步骤操作比 heappop()加 heappush() 更高效,并且在使用固定大小的堆时更为适宜。 pop/push 组合总是会从堆中返回一个元素并将其替换为 num。
返回的值可能会比添加的 num 更大。 如果不希望如此,可考虑改用 heappushpop()。 它的 push/pop 组合会返回两个值中较小的一个,将较大的值留在堆中。
heapreplace(li,7)
print(li)
输出:
[2, 3, 4, 3, 7, 5, 8]
heapq.
merge(li,li2)
将多个堆合并
from heapq import*
li=[1, 1, 4, 2, 3, 5, 8]
li1=[2,1,2,3,2,4,6]
heapify(li)
heapify(li1)
lists=merge(li,li1)
print(list(lists))
输出:
[1, 1, 2, 1, 2, 3, 2, 4, 2, 3, 4, 5, 6, 8]
heapq.
nlargest
(n, li, key=None)从 li 所定义的数据集中返回前 n 个最大元素组成的列表。 如果提供了 key 则其应指定一个单参数的函数,用于从 li 的每个元素中提取比较键 (例如 key=str.lower
)。
from heapq import*
li1=["Jsfas","sdaks","Ksfaz","gdssd"]
heapify(li1)
print(li1)#原堆
list1=nlargest(2,li1,key=str.lower)#有key的输出
list2=nlargest(2,li1)#没key的输出
print(list1)
print(list2)
输出:
['Jsfas', 'gdssd', 'Ksfaz', 'sdaks']
['sdaks', 'Ksfaz']
['sdaks', 'gdssd']
heapq.
nsmallest
(n, li, key=None)从 li 所定义的数据集中返回前 n 个最小元素组成的列表。 如果提供了 key 则其应指定一个单参数的函数,用于从 li 的每个元素中提取比较键 (例如 key=str.lower
)
同上原理
def heapsort(li):
h = []
for value in li:
heappush(h, value)
return [heappop(h) for i in range(len(h))]
print(heapsort([1, 3, 5, 7, 9, 2, 4, 6, 8, 0]))
输出:
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]