数据结构:优先队列 基于堆实现(python版)

 1 #!/usr/bin/env python
 2 # -*- coding:utf-8 -*-
 3 
 4 '''
 5 Author: Minion-Xu
 6 '''
 7 
 8 #异常类
 9 class HeapPriQueueError(ValueError):
10     pass
11 
12 class Heap_Pri_Queue(object):
13     def __init__(self, elems = []):
14         self._elems = list(elems)
15         if self._elems:
16             self.buildheap()
17 
18     #判断是否为空
19     def is_empty(self):
20         return self._elems is []
21 
22     #查看堆顶元素,即优先级最低元素
23     def peek(self):
24         if self.is_empty():
25             raise HeapPriQueueError("in pop")
26         return self._elems[0]
27 
28     #将新的优先级加入队列 O(logn)
29     def enqueue(self, e):
30         #在队列末尾创建一个空元素
31         self._elems.append(None)
32         self.siftup(e, len(self._elems) - 1)
33 
34     #新的优先级默认放在末尾,因此失去堆序,进行siftup构建堆序
35     #将e位移到真确的位置
36     def siftup(self, e, last):
37         elems, i, j = self._elems, last, (last-1)//2 #j为i的父节点
38         while i>0 and e < elems[j]:
39             elems[i] = elems[j]
40             i, j = j, (j-1)//2
41         elems[i] = e
42 
43     #堆顶值最小优先级最高的出队,确保弹出元素后任然维持堆序
44     #将最后的元素放在堆顶,然后进行siftdown
45     #  O(logn)
46     def dequeue(self):
47         if self.is_empty():
48             raise HeapPriQueueError("in pop")
49         elems = self._elems
50         e0 = elems[0]
51         e = elems.pop()
52         if len(elems)>0:
53             self.siftdown(e, 0, len(elems))
54         return e0
55 
56     def siftdown(self, e, begin, end):
57         elems, i, j = self._elems, begin, begin*2 + 1
58         while j < end:
59             if j+1 < end and elems[j] > elems[j+1]:
60                 j += 1
61             if e < elems[j]:
62                 break
63             elems[i] = elems[j]
64             i, j = j, j*2+1
65         elems[i] = e
66 
67     #构建堆序 O(n)
68     def buildheap(self):
69         end = len(self._elems)
70         for i in range(end//2, -1, -1):
71             self.siftdown(self._elems[i], i, end)
72 
73 
74 if __name__=="__main__":
75     l = Heap_Pri_Queue([5,6,1,2,4,8,9,0,3,7])
76     print(l._elems)
77     #[0, 2, 1, 3, 4, 8, 9, 6, 5, 7]
78     l.dequeue()
79     print(l._elems)
80     #[1, 2, 7, 3, 4, 8, 9, 6, 5]
81     print(l.is_empty())
82     l.enqueue(0)
83     print(l._elems)
84     print(l.peek())

插入元素:末尾插入, 向上筛选(siftup)

弹出元素:堆顶弹出, 末尾元素充当堆顶, 向下筛选(siftdown)

原文地址:https://www.cnblogs.com/xautxuqiang/p/6129198.html