python deque heapq详解

概念

deque模块是python标准库collections中的一项,它提供了两端都可以操作的序列,这意味着,在序列的前后你都可以执行添加或删除操作。

使用deque(maxlen=N) 构造函数会新建一个固定大小的队列。当新的元素加入并且这个队列已经满的时候, 最老的元素会被替换掉的。

from collections import deque
q = deque(maxlen=3)
q.append(1)
q.append(2)
q.append(3)
print(q) #deque([1, 2, 3], maxlen=3)
q.append(4)
q.append(5)
print(q) # deque([3, 4, 5], maxlen=3)

可以在队列的两端 增加删除

q.appendleft(6)
print(q) #deque([6, 3, 4], maxlen=3)

p = q.pop()
print(p) #4
print(q) #deque([6, 3], maxlen=3)
print(q.popleft()) #6

获取最大或者最小的N个元素

使用heapq 解决

import heapq

"""获取最大或者最小的元素"""
nums = [1,3, 9,10, 44, 32,2,34,52,21]
print(heapq.nlargest(3, nums)) #[52, 44, 34]
print(heapq.nsmallest(3, nums)) #[1, 2, 3]

接受关键字参数, 用于复杂的数据结构

portfolio = [
    {'name': 'IBM', 'shares': 100, 'price': 91.1},
    {'name': 'AAPL', 'shares': 50, 'price': 543.22},
    {'name': 'FB', 'shares': 200, 'price': 21.09},
    {'name': 'HPQ', 'shares': 35, 'price': 31.75},
    {'name': 'YHOO', 'shares': 45, 'price': 16.35},
    {'name': 'ACME', 'shares': 75, 'price': 115.65}
]
cheap = heapq.nlargest(3, portfolio, key=lambda s: s['price'])
expensive = heapq.nsmallest(3, portfolio, key=lambda s: s['price'])

print(cheap)
# [{'name': 'AAPL', 'shares': 50, 'price': 543.22}, {'name': 'ACME', 'shares': 75, 'price': 115.65}, {'name': 'IBM', 'shares': 100, 'price': 91.1}]
print(expensive)# [{'name': 'YHOO', 'shares': 45, 'price': 16.35}, {'name': 'FB', 'shares': 200, 'price': 21.09}, {'name': 'HPQ', 'shares': 35, 'price': 31.75}]

以上进行比较的时候是根据price 进行比较的, 支持key , 就像是sorted 排序一样

总结:
对于取最大值最小值, 几种方法比较和使用
- heapq.nlargest() : 当查找的元素个数相对比较小的时候
- max(),min() : 当仅仅查找唯一的最大值最小值时候
- sorted(items, key=) [:N】: 当N的大小和集合的大小比较接近时候,通常先排序再切片操作


heapq 的使用
下面是对应的函数
heapq.heappush(heap, item) 把item添加到heap中(heap是一个列表)

heapq.heappop(heap) 把堆顶元素弹出,返回的就是堆顶

heapq.heappushpop(heap, item) 先把item加入到堆中,然后再pop,比heappush()再heappop()要快得多

heapq.heapreplace(heap, item) 先pop,然后再把item加入到堆中,比heappop()再heappush()要快得多

heapq.heapify(x) 将列表x进行堆调整,默认的是小顶堆

heapq.merge(*iterables) 将多个列表合并,并进行堆调整,返回的是合并后的列表的迭代器

heapq.nlargest(n, iterable, key=None) 返回最大的n个元素(Top-K问题)

heapq.nsmallest(n, iterable, key=None) 返回最小的n个元素(Top-K问题)


实现按照优先级排列的队列

print("heapq 是基于heap 堆的优先排序的算法")
import heapq


class PriorityQueue(object):
    def __init__(self):
        self._queue = []
        self._index = 0

    def push(self, item, priority):
        heapq.heappush(self._queue, (-priority, self._index, item))
        self._index += 1

    def pop(self):
        return heapq.heappop(self._queue)[-1]

class Item(object):
    def __init__(self, name):
        self.name = name
    def __repr__(self):
        return 'Item({!r})'.format(self.name)

q = PriorityQueue()
q.push(Item('foo'), 1)
q.push(Item('bar'), 5)
q.push(Item('spam'), 4)
q.push(Item('grok'), 1)

print(q.pop()) # Item('bar')
print(q.pop()) # Item('spam')
print(q.pop()) #  Item('foo')

按照优先级等级(下面这个是上面的简化版)

import heapq
import random
# mylist = list(random.sample(range(100), 10))
mylist = []
heapq.heappush(mylist, (-3, 2, 3, 5))
heapq.heappush(mylist, (-6, 2, 3, 1))
heapq.heappush(mylist, (5, 2, 3, 7))


print(mylist) #[(-6, 2, 3, 1), (-3, 2, 3, 5), (5, 2, 3, 7)]
print(heapq.heappop(mylist)) # (-6, 2, 3, 1)
print(heapq.heappop(mylist)[-1]) #5
print(heapq.heappop(mylist)[-1])# 7

分析:
第一个代表的是权重, 如果使用元组, 相同权重的优先级不能进行比较的。 所以在PriorityQueue 类的push方法 中使用了一个index 就确保了在第一个元素, 权重相同的情况下,就会直接 根据index 来进行排序和权重,这样 最后一个元素不是可迭代,不能进行排序的时候就不会报错,又可以取到。 所以中间用一个index 来进行自加, 这样就避免了这个出现重复的问题权重问题。排序是按照先后顺序的。

字典映射等多个值

print('=========')
from collections import defaultdict
d = defaultdict(list)
d['a'].append(1)
d['a'].append(2)
d['a'].append(4)

print(d) # defaultdict(<class 'list'>, {'a': [1, 2, 4]})
print(d['a']) #[1, 2, 4]

print("======set()")
d = defaultdict(set) # 是list 添加还是set添加在defaultdict() 中定义
d['a'].add(1)
d['a'].add(3)
d['b'].add(9)
print(d) # defaultdict(<class 'set'>, {'a': {1, 3}, 'b': {9}})

创建多值映射字典

d = defaultdict(list)
for key, value in pairs:
    d[key].append(value)
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值