Python成为专业人士笔记–Heapq 堆操作

“专业人士笔记”系列目录:

创帆云:Python成为专业人士笔记--强烈建议收藏!每日持续更新!

堆介绍

一种著名的数据结构是堆(heap),它是一种优先队列。优先队列让你能够以任意顺序添加对象,并随时(可能是在两次添加对象之间)找出(并删除)最小的元素。相比于列表方法min,这样做的效率要高得多。

实际上,Python没有独立的堆类型,而只有一个包含一些堆操作函数的模块。这个模块名为heapq(其中的q表示队列),它包含6个函数,其中前4个与堆操作直接相关。必须使用列表来表示堆对象本身。

v2-b0d0d67abb9b2dc4542722f20ea58e59_b.jpg

堆类型类型中最大和最小值

要查找堆中最大的项,heapq模块有一个名为nlargest的函数,我们向它传递两个参数,第一个参数是要返回的元素个数,第二个参数是集合类型变量名

        import heapq

numbers = [1, 4, 2, 100, 20, 50, 32, 200, 150, 8]
print(heapq.nlargest(4, numbers))

# 输出:[200, 150, 100, 50]
      

类似地,为了找到集合烦躁中最小的元素,我们使用 nsmallest函数:

        import heapq 
numbers = [1, 4, 2, 100, 20, 50, 32, 200, 150, 8] 
print(heapq.nsmallest(4, numbers))

#输出:[1, 2, 4, 8】
      

对于复杂的数据结构,nlargest和 nsmallest 函数都采用一些可选的关键参数。下面的示例演示了如何使用age属性从people字典中检索最年长和最年轻的人

        import heapq

people = [

    {'firstname': 'John', 'lastname': 'Doe', 'age': 30},

    {'firstname': 'Jane', 'lastname': 'Doe', 'age': 25},

    {'firstname': 'Janie', 'lastname': 'Doe', 'age': 10},

    {'firstname': 'Jane', 'lastname': 'Roe', 'age': 22},

    {'firstname': 'Johnny', 'lastname': 'Doe', 'age': 12},

    {'firstname': 'John', 'lastname': 'Roe', 'age': 45}
]

oldest = heapq.nlargest(2, people, key=lambda s: s['age'])
print(oldest)

# 输出: [{'firstname': 'John', 'age': 45, 'lastname': 'Roe'}, {'firstname': 'John', 'age': 30,'lastname': 'Doe'}]

#使用了key参数,利用匿名函数将key指定为每个字典元素的age属性


youngest = heapq.nsmallest(2, people, key=lambda s: s['age'])
print(youngest)

# 输出: [{'firstname': 'Janie', 'age': 10, 'lastname': 'Doe'}, {'firstname': 'Johnny', 'age': 12,'lastname': 'Doe'}]

#原理同上

      

最小元素弹出

堆最有趣的属性是它的最小元素始终是第一个元素:heap [0]

        import heapq

numbers = [10, 4, 2, 100, 20, 50, 32, 200, 150, 8]
heapq.heapify(numbers)  #将列表就地转换为堆

print(numbers)
# 输出: [2, 4, 10, 100, 8, 50, 32, 200, 150, 20]   堆的第一个元素一定是最小的那个值

heapq.heappop(numbers)
# 删除最小的值最返回:2
print(numbers)
# 输出: [4, 8, 10, 100, 20, 50, 32, 200, 150]

heapq.heappop(numbers)
# 删除最小的值最返回:4
print(numbers)
# 输出: [8, 20, 10, 100, 150, 50, 32, 200]

      

也许你看到每次输出堆的排列顺序非常随意,其实其并不像看起来的这样。它们虽然不是严格排序的,但必须保证一点:位置i处的元素总是大于位置i // 2处的元素(反过来说就是小于位置2 * i和2 * i + 1处的元素)。这是底层堆算法的基础,称为堆特征(heap property)。

猜你喜欢

转载自blog.csdn.net/oSuiYing12/article/details/106211759