堆
堆(英语:heap)是计算机科学中一类特殊的数据结构的统称。堆通常是一个可以被看做一棵树的数组对象。堆总是满足下列性质:
堆中某个节点的值总是不大于或不小于其父节点的值;
堆总是一棵完全二叉树。
将根节点最大的堆叫做最大堆或大根堆,根节点最小的堆叫做最小堆或小根堆
基于数组的完全二叉树表示
如果p是T的根节点,则f§=0
如果p是位置q的左孩子,则 f§=2f(q)+1
如果p是位置q的右孩子,则f§=2f(q)+2
1我们用数组来表示一棵二叉树
自底向上构建堆
如初始序列为 3 4 5 7 9 1 2 10 11
完全二叉树
根据这个完全二叉树构造成小根堆,就要从最后一个具有孩子节点的节点开始不断让其向下调整 ,所以应该从7开始调整,它是最后一个节点的双亲节点所以很容易定位到它 7比2小交换 然后接着调整5 5比1小交换 接着调整4 4 比2小交换 最后调整3 3比1小交换
基于堆的优先级队列实现
class Empty:
pass
class PriorityQueueBase:
class _Item:
def __init__(self,k,v):
self._key=k#键
self._value=v#值
def __It__(self,other):
return self._key<other._key
def is_empty(self):
return len(self)==0
class HeapPriorityQueue(PriorityQueueBase):
def __init__(self,content=()):#初始化,用列表作为存储结构
#self._data=[]
self._data=[self._Item(k,v) for k,v in content]
if len(self._data)>1:
self._heapify()
def _heapify(self):
start = self._parent(len(self._data) - 1)
for i in range(start, -1, -1):
self._downheap(i)
def _parent(self,j):#返回下标为j的元素的父节点下标
return (j-1)//2
def _left(self,j):#返回下标为j的元素的左孩子下标
return 2*j+1
def _right(self,j):#返回下标为j的元素的右孩子下标
return 2*j+2
def _has_left(self,j):#判断下标为j的元素是否有左孩子
return self._left(j)<len(self._data)
def _has_right(self,j):#判断下标为j的元素是否有右孩子
return self._right(j)<len(self._data)
def _swap(self,i,j):#交换self._data数组中下标为i,j的值
self._data[i],self._data[j]=self._data[j],self._data[i]
def _upheap(self,j):#自下而上的调整堆
parent=self._parent(j)
if j>0 and self._data[j].__It__(self._data[parent]):
self._swap(j,parent)
self._upheap(parent)
def _downheap(self,j):#自上而下的调整堆
if self._has_left(j):
left=self._left(j)
smallchild=left
if self._has_right(j):
right=self._right(j)
if self._data[right].__It__(self._data[left]):
smallchild=right
if self._data[smallchild].__It__(self._data[j]):
self._swap(j,smallchild)
self._downheap(smallchild)
def __len__(self):
return len(self._data)
def add(self,key,value):
node=self._Item(key,value)
self._data.append(node)
self._upheap(len(self._data)-1)
def min(self):
if self.is_empty():
raise Empty('Priority queue is empty')
item=self._data[0]
return (item._key,item._value)
def remove_min(self):
if self.is_empty():
raise Empty('Priority queue is empty')
self._swap(0, len(self._data) - 1)
item=self._data.pop()
self._downheap(0)
return (item._key,item._value)
HPQ=HeapPriorityQueue()
HPQ.add(10,2)
HPQ.add(9,2)
HPQ.add(5,3)
HPQ.add(8,7)
HPQ.add(1,3)
print(HPQ.min())
print(HPQ.remove_min())
print(HPQ.remove_min())
print(HPQ.remove_min())
基于堆的优先级队列的分析
操作 | 未排序列表 |
---|---|
Len | O(1) |
is_empty | O(1) |
add | O(logn) |
min | O(1) |
remove_min | O(logn) |