1.5 实现优先级队列

问题:

实现一个队列,能够按照给定的优先级排序,并且每次pop操作时都可以返回优先级最高的那个元素.

解决方案

1.import heapq
2.class PriorityQueue:
3. def __init__(self):
4. self._queue=[]
5. self._index=0
6. def push(self,item,priority):
7. heapq.heappush(self._queue,(-priority,self._index,item))
8. self._index +=1
9. def pop(self):
10. return heapq.heappop(self._queue)[-1]
11.
12.
13.class Item:
14. def __init__(self,name):
15. self.name = name
16. def __repr__(self):
17. return 'Item({!r})'.format(self.name)
18.
19.q=PriorityQueue()
20.q.push(Item('foo'),3)
21.q.push(Item('bar'),4)
22.q.push(Item('spam'),3)
23.
24.print(q.pop())
25.print(q.pop())
26.print(q.pop())

讨论

  1. 这段代码的核心在于heapq中的push和pop操作. push和pop的复杂度为O(logN)总的来说,效率相对较高.
  2. heapq是一个最小堆. 也就是说,堆中的对象必须是可以比较大小的. 而Item的实例并不能比较大小. 所以我们可以构造一个元组(priority,item)但是这样做不到所有数据的唯一性. 因此,再加一个index

知识补充

heapq模块

  • heap是一个二叉树结构,初始化为一个空列表. 其父节点永远比子节点小.heap[k] <= heap[2*k+1] and heap[k] <= heap[2*k+2] for all k, counting elements from zero.
  • python中的heap是一个最小堆,也就是说,heap[0]永远是最小的那个元素.
  • 常用函数:
    • heapq.heappush(heap,item) push操作
    • heapq.heappop(heap) pop操作,每次返回heap[0],如果heap空了,则抛出IndexError异常
    • heapq.heappushpop(heap, item) push&pop
    • heapq.heapify(x) 将一个list转化为heap
    • heapq.heapreplace(heap, item) 与pushpop不同,这个是先pop再push. 如果遇到空的heap会出现IndexError的异常.
    • heapq.merge(*iterables, key=None, reverse=False) 合并,不知道有啥用…
    • heapq.nlargest(n, iterable, key=None)
    • heapq.nsmallest(n, iterable, key=None)

比如实现一个简单的堆排序

1.def heapsort(iterable):
2. h=[]
3. for value in iterable:
4. heapq.heappush(h,value)
5. return[heapq.heappop(h) for i in range(len(h))]

repr和str函数

所有官方文档都在说,str函数是给人看的,repe函数是给编译器看的.

1. class Item:
2. def __init__(self,name):
3. self.name = name
4. def __str__(self):
5. return 'here is {0} __str__ function'.format(self.name)
6. def __repr__(self):
7. return 'here is {0} __repr__ function'.format(self.name)
8.>>> boo = Item('boo')
9.>>> boo
10.here is boo __repr__ function
11.>>> print(boo)
12.here is boo __str__ function

通过上面这段代码简单来看,在repr函数没有重载的时候,默认会显示<main.Item object at 0x03CC1D70>类似这个样子,是一个地址. 也就是说这两个函数都是用来显示关于这个类的信息的. 而print函数会调用str函数,解释器会调用repr函数.

format()函数
format函数用于做str的格式化书写.可以使用{}来做占位符以提供一个模板.
比如:

1.#1.使用数字占位符
2.>>> "User ID: {0}".format("root")
3.'User ID: root'
4.#2.使用类似变量的占位符
5.>>> 'User ID: {uid} Last seen: {last_login}'.format(uid='root',last_login = '5 Mar 2008 07:20')
6.'User ID: root Last seen: 5 Mar 2008 07:20'
7.#3.大括号的转义
8.format("Empty dict: {{}}")
9.#4.在字典中使用
10.>>> d2={'jim':25,'tom':27}
11.>>> "jim's age is {0[jim]}".format(d2)
12."jim's age is 25"

另外关于三个控制字符,Three conversion flags are currently supported: ‘!s’ which calls str() on the value, ‘!r’ which calls repr() and ‘!a’ which calls ascii().
>>> '{0},{1!r}'.format(boo,boo)
'here is boo __str__ function,here is boo __repr__ function'

更具体的用法查文档吧…

%231.5%20%u5B9E%u73B0%u4F18%u5148%u7EA7%u961F%u5217%0A@%28python%29%5Bcookbook%7C%u6570%u636E%u7ED3%u6784%u4E0E%u7B97%u6CD5%5D%0A%0A%23%23%u95EE%u9898%3A%0A%u5B9E%u73B0%u4E00%u4E2A%u961F%u5217%2C%u80FD%u591F%u6309%u7167%u7ED9%u5B9A%u7684%u4F18%u5148%u7EA7%u6392%u5E8F%2C%u5E76%u4E14%u6BCF%u6B21pop%u64CD%u4F5C%u65F6%u90FD%u53EF%u4EE5%u8FD4%u56DE%u4F18%u5148%u7EA7%u6700%u9AD8%u7684%u90A3%u4E2A%u5143%u7D20.%0A%0A%23%23%u89E3%u51B3%u65B9%u6848%0A%60%60%60python%0Aimport%20heapq%0Aclass%20PriorityQueue%3A%0A%09def%20__init__%28self%29%3A%0A%09%09self._queue%3D%5B%5D%0A%09%09self._index%3D0%0A%09def%20push%28self%2Citem%2Cpriority%29%3A%0A%09%09heapq.heappush%28self._queue%2C%28-priority%2Cself._index%2Citem%29%29%0A%09%09self._index%20+%3D1%0A%09def%20pop%28self%29%3A%0A%09%09return%20heapq.heappop%28self._queue%29%5B-1%5D%0A%0A%0Aclass%20Item%3A%0A%09def%20__init__%28self%2Cname%29%3A%0A%09%09self.name%20%3D%20name%0A%09def%20__repr__%28self%29%3A%0A%09%09return%20%27Item%28%7B%21r%7D%29%27.format%28self.name%29%0A%0Aq%3DPriorityQueue%28%29%0Aq.push%28Item%28%27foo%27%29%2C3%29%0Aq.push%28Item%28%27bar%27%29%2C4%29%0Aq.push%28Item%28%27spam%27%29%2C3%29%0A%09%09%0Aprint%28q.pop%28%29%29%0Aprint%28q.pop%28%29%29%0Aprint%28q.pop%28%29%29%0A%60%60%60%0A%23%23%u8BA8%u8BBA%0A1.%20%u8FD9%u6BB5%u4EE3%u7801%u7684%u6838%u5FC3%u5728%u4E8Eheapq%u4E2D%u7684push%u548Cpop%u64CD%u4F5C.%20push%u548Cpop%u7684%u590D%u6742%u5EA6%u4E3AO%28logN%29%u603B%u7684%u6765%u8BF4%2C%u6548%u7387%u76F8%u5BF9%u8F83%u9AD8.%0A2.%20heapq%u662F%u4E00%u4E2A%u6700%u5C0F%u5806.%20%u4E5F%u5C31%u662F%u8BF4%2C%u5806%u4E2D%u7684%u5BF9%u8C61%u5FC5%u987B%u662F%u53EF%u4EE5%u6BD4%u8F83%u5927%u5C0F%u7684.%20%u800CItem%u7684%u5B9E%u4F8B%u5E76%u4E0D%u80FD%u6BD4%u8F83%u5927%u5C0F.%20%u6240%u4EE5%u6211%u4EEC%u53EF%u4EE5%u6784%u9020%u4E00%u4E2A%u5143%u7EC4%28priority%2Citem%29%u4F46%u662F%u8FD9%u6837%u505A%u4E0D%u5230%u6240%u6709%u6570%u636E%u7684%u552F%u4E00%u6027.%20%u56E0%u6B64%2C%u518D%u52A0%u4E00%u4E2Aindex%0A%23%23%u77E5%u8BC6%u8865%u5145%0A**heapq%u6A21%u5757**%0A-%20heap%u662F%u4E00%u4E2A%u4E8C%u53C9%u6811%u7ED3%u6784%2C%u521D%u59CB%u5316%u4E3A%u4E00%u4E2A%u7A7A%u5217%u8868.%20%u5176%u7236%u8282%u70B9%u6C38%u8FDC%u6BD4%u5B50%u8282%u70B9%u5C0F.heap%5Bk%5D%20%3C%3D%20heap%5B2*k+1%5D%20and%20heap%5Bk%5D%20%3C%3D%20heap%5B2*k+2%5D%20for%20all%20k%2C%20counting%20elements%20from%20zero.%0A-%20python%u4E2D%u7684heap%u662F%u4E00%u4E2A%u6700%u5C0F%u5806%2C%u4E5F%u5C31%u662F%u8BF4%2Cheap%5B0%5D%u6C38%u8FDC%u662F%u6700%u5C0F%u7684%u90A3%u4E2A%u5143%u7D20.%20%0A-%20%u5E38%u7528%u51FD%u6570%3A%0A%09-%20heapq.heappush%28heap%2Citem%29%20push%u64CD%u4F5C%0A%09-%20heapq.heappop%28heap%29%20pop%u64CD%u4F5C%2C%u6BCF%u6B21%u8FD4%u56DEheap%5B0%5D%2C%u5982%u679Cheap%u7A7A%u4E86%2C%u5219%u629B%u51FAIndexError%u5F02%u5E38%0A%09-%20heapq.heappushpop%28heap%2C%20item%29%20push%26pop%0A%09-%20heapq.heapify%28x%29%20%u5C06%u4E00%u4E2Alist%u8F6C%u5316%u4E3Aheap%0A%09-%20heapq.heapreplace%28heap%2C%20item%29%20%u4E0Epushpop%u4E0D%u540C%2C%u8FD9%u4E2A%u662F%u5148pop%u518Dpush.%20%u5982%u679C%u9047%u5230%u7A7A%u7684heap%u4F1A%u51FA%u73B0IndexError%u7684%u5F02%u5E38.%0A%09-%20heapq.merge%28*iterables%2C%20key%3DNone%2C%20reverse%3DFalse%29%20%u5408%u5E76%2C%u4E0D%u77E5%u9053%u6709%u5565%u7528...%0A%09-%20heapq.nlargest%28n%2C%20iterable%2C%20key%3DNone%29%0A%09-%20heapq.nsmallest%28n%2C%20iterable%2C%20key%3DNone%29%20%0A%0A%u6BD4%u5982%u5B9E%u73B0%u4E00%u4E2A%u7B80%u5355%u7684%u5806%u6392%u5E8F%0A%60%60%60python%0Adef%20heapsort%28iterable%29%3A%0A%09h%3D%5B%5D%0A%09for%20value%20in%20iterable%3A%0A%09%09heapq.heappush%28h%2Cvalue%29%0A%09return%5Bheapq.heappop%28h%29%20for%20i%20in%20range%28len%28h%29%29%5D%0A%60%60%60%0A%0A**repr%u548Cstr%u51FD%u6570**%0A%0A%u6240%u6709%u5B98%u65B9%u6587%u6863%u90FD%u5728%u8BF4%2Cstr%u51FD%u6570%u662F%u7ED9%u4EBA%u770B%u7684%2Crepe%u51FD%u6570%u662F%u7ED9%u7F16%u8BD1%u5668%u770B%u7684.%20%0A%60%60%60python%0A%20class%20Item%3A%0A%09def%20__init__%28self%2Cname%29%3A%0A%09%09self.name%20%3D%20name%0A%09def%20__str__%28self%29%3A%0A%09%09return%20%27here%20is%20%7B0%7D%20__str__%20function%27.format%28self.name%29%0A%09def%20__repr__%28self%29%3A%0A%09%09return%20%27here%20is%20%7B0%7D%20__repr__%20function%27.format%28self.name%29%0A%3E%3E%3E%20boo%20%3D%20Item%28%27boo%27%29%0A%3E%3E%3E%20boo%0Ahere%20is%20boo%20__repr__%20function%0A%3E%3E%3E%20print%28boo%29%0Ahere%20is%20boo%20__str__%20function%0A%60%60%60%0A%u901A%u8FC7%u4E0A%u9762%u8FD9%u6BB5%u4EE3%u7801%u7B80%u5355%u6765%u770B%2C%u5728repr%u51FD%u6570%u6CA1%u6709%u91CD%u8F7D%u7684%u65F6%u5019%2C%u9ED8%u8BA4%u4F1A%u663E%u793A%3C__main__.Item%20object%20at%200x03CC1D70%3E%u7C7B%u4F3C%u8FD9%u4E2A%u6837%u5B50%2C%u662F%u4E00%u4E2A%u5730%u5740.%20%u4E5F%u5C31%u662F%u8BF4%u8FD9%u4E24%u4E2A%u51FD%u6570%u90FD%u662F%u7528%u6765%u663E%u793A%u5173%u4E8E%u8FD9%u4E2A%u7C7B%u7684%u4FE1%u606F%u7684.%20%u800Cprint%u51FD%u6570%u4F1A%u8C03%u7528str%u51FD%u6570%2C%u89E3%u91CA%u5668%u4F1A%u8C03%u7528repr%u51FD%u6570.%0A%0A**format%28%29%u51FD%u6570**%0Aformat%u51FD%u6570%u7528%u4E8E%u505Astr%u7684%u683C%u5F0F%u5316%u4E66%u5199.%u53EF%u4EE5%u4F7F%u7528%7B%7D%u6765%u505A%u5360%u4F4D%u7B26%u4EE5%u63D0%u4F9B%u4E00%u4E2A%u6A21%u677F.%0A%u6BD4%u5982%3A%0A%60%60%60python%0A%231.%u4F7F%u7528%u6570%u5B57%u5360%u4F4D%u7B26%0A%3E%3E%3E%20%22User%20ID%3A%20%7B0%7D%22.format%28%22root%22%29%0A%27User%20ID%3A%20root%27%0A%232.%u4F7F%u7528%u7C7B%u4F3C%u53D8%u91CF%u7684%u5360%u4F4D%u7B26%0A%3E%3E%3E%20%27User%20ID%3A%20%7Buid%7D%20Last%20seen%3A%20%7Blast_login%7D%27.format%28uid%3D%27root%27%2Clast_login%20%3D%20%275%20Mar%202008%2007%3A20%27%29%0A%27User%20ID%3A%20root%20Last%20seen%3A%205%20Mar%202008%2007%3A20%27%0A%233.%u5927%u62EC%u53F7%u7684%u8F6C%u4E49%0Aformat%28%22Empty%20dict%3A%20%7B%7B%7D%7D%22%29%0A%234.%u5728%u5B57%u5178%u4E2D%u4F7F%u7528%0A%3E%3E%3E%20d2%3D%7B%27jim%27%3A25%2C%27tom%27%3A27%7D%0A%3E%3E%3E%20%22jim%27s%20age%20is%20%7B0%5Bjim%5D%7D%22.format%28d2%29%0A%22jim%27s%20age%20is%2025%22%0A%60%60%60%0A%u53E6%u5916%u5173%u4E8E%u4E09%u4E2A%u63A7%u5236%u5B57%u7B26%2CThree%20conversion%20flags%20are%20currently%20supported%3A%20%27%21s%27%20which%20calls%20str%28%29%20on%20the%20value%2C%20%27%21r%27%20which%20calls%20repr%28%29%20and%20%27%21a%27%20which%20calls%20ascii%28%29.%0A%60%3E%3E%3E%20%27%7B0%7D%2C%7B1%21r%7D%27.format%28boo%2Cboo%29%0A%27here%20is%20boo%20__str__%20function%2Chere%20is%20boo%20__repr__%20function%27%60%0A%0A%u66F4%u5177%u4F53%u7684%u7528%u6CD5%u67E5%u6587%u6863%u5427...%0A%0A