zoukankan      html  css  js  c++  java
  • python3-开发进阶 heapq模块(如何查找最大或最小的N个元素)

    一、怎样从一个集合中获得最大或者最小的 N 个元素列表?

      heapq 模块有两个函数:nlargest() 和 nsmallest() 可以完美解决这个问题。

    import heapq
    nums = [1, 8, 2, 23, 7, -4, 18, 23, 42, 37, 2]
    print(heapq.nlargest(3, nums)) # Prints [42, 37, 23]
    print(heapq.nsmallest(3, nums)) # Prints [-4, 1, 2]
    
    #前面的参数可选多个元素

      两个函数都能接受一个关键字参数,用于更复杂的数据结构中:

    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.nsmallest(3, portfolio, key=lambda s: s['price'])
    expensive = heapq.nlargest(3, portfolio, key=lambda s: s['price'])

    PS:上面代码在对每个元素进行对比的时候,会以 price 的值进行比较。

    二、如何查找最大或最小的 N 个元素

    nums = [1, 8, 2, 23, 7, -4, 18, 23, 42, 37, 2]
    import heapq
    heapq.heapify(nums)
    print(nums)
    #[-4, 2, 1, 23, 7, 2, 18, 23, 42, 37, 8]

      堆数据结构最重要的特征是 heap[0] 永远是最小的元素。并且剩余的元素可以很
    容易的通过调用 heapq.heappop() 方法得到,该方法会先将第一个元素弹出来,然后
    用下一个最小的元素来取代被弹出元素 (这种操作时间复杂度仅仅是 O(log N),N 是
    堆大小)。

    如果想要查找最小的 3 个元素,你可以这样做:

    heapq.heappop(nums)
    #-4
    heapq.heappop(nums)
    #1
    heapq.heappop(nums)
    #2

    当要查找的元素个数相对比较小的时候,函数 nlargest() 和 nsmallest() 是很
    合适的。如果你仅仅想查找唯一的最小或最大 (N=1) 的元素的话,那么使用 min() 和
    max() 函数会更快些。类似的,如果 N 的大小和集合大小接近的时候,通常先排序这
    个集合然后再使用切片操作会更快点 ( sorted(items)[:N] 或者是 sorted(items)[-
    N:] )。需要在正确场合使用函数 nlargest() 和 nsmallest() 才能发挥它们的优势 (如果
    N 快接近集合大小了,那么使用排序操作会更好些)

     三、实现一个优先级队列

    怎样实现一个按优先级排序的队列?并且在这个队列上面每次 pop 操作总是返回
    优先级最高的那个元素

    下面的类利用 heapq 模块实现了一个简单的优先级队列:

    import heapq
    class PriorityQueue:
        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:
    ... 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)
    >>> q.pop()
    Item('bar')
    >>> q.pop()
    Item('spam')
    >>> q.pop()
    Item('foo')
    >>> q.pop()
    Item('grok')

    仔细观察可以发现,第一个 pop() 操作返回优先级最高的元素。另外注意到如果
    两个有着相同优先级的元素 ( foo 和 grok ),pop 操作按照它们被插入到队列的顺序返
    回的。

  • 相关阅读:
    HDOJ 4747 Mex
    HDU 1203 I NEED A OFFER!
    HDU 2616 Kill the monster
    HDU 3496 Watch The Movie
    Codeforces 347A A. Difference Row
    Codeforces 347B B. Fixed Points
    Codeforces 372B B. Hungry Sequence
    HDU 1476 Sudoku Killer
    HDU 1987 How many ways
    HDU 2564 词组缩写
  • 原文地址:https://www.cnblogs.com/ManyQian/p/9291663.html
Copyright © 2011-2022 走看看