之前的队列(queue)都是先进先出的数据结构。然而在优先队列中,在队列里的数据都有一个优先级标签。 在优先级队列中,队列的项的逻辑顺序由他们的优先级决定。最高优先级在队列的前面,最低优先级在项的后面。
实现优先级队列的经典方法是使用成为二叉堆的数据结构,它可以在O(log(n))时间中排队和取出队列
什么是二叉堆
二叉堆(binary heap),这个堆(heap)在结构上是一棵完全二叉树,在实现上使用的数组list,采用数组的index值表示父结点及子结点。二叉堆有两个常见的变体:最小堆(其中最小的键总是在前面)和最大堆。
由于二叉堆要是一个完全二叉树,所以为了保证log(n)的时间量,必须保证树是平衡的。
如图是一个二叉堆,堆的结构类似树,实现方式由list实现。list的第一个元素是0,至于为什么要这样呢?因为树上的每一个元素都有对应的index,要满足左右结点分别是2*p
& 2*p+1
,如果索引index是从0开始,则不满足。
二叉堆的属性是一个很重要的东西,二叉堆的所有操作基本都基于它的属性:每个结点的父结点都比它本身要小 (最小堆)
二叉堆的构造
class BinaryHeap:
def __init__(self):
self.__heap_list = [0]
self.__size = 0
二叉堆的插入
在二叉堆中插入一个项,过程是:将这个要插入的项置于二叉堆list的最后一项,由于二叉堆要保持它的属性(每个结点的父结点都比它本身要小),这个项与其父结点进行比较,小的在上,大的在下进行可能的交换,这种比较要一直持续到根结点
这种交换由于是将待插入的项从下往上交换,所以叫做go_up
def go_up(self, index):
while index // 2 > 0:
if self.__heap_list[index] < self.__heap_list[index // 2]:
self.__heap_list[index], self.__heap_list[index // 2] = self.__heap_list[index // 2], self.__heap_list[index]
index = index // 2
def insert(self, data):
self.__heap_list.append(data)
self.__size = self.__size + 1
self.go_up(self.__size)
二叉堆的删除
由于我们研究的是最小堆,所以出队操作是移出值最小的那个结点,即根结点。
具体操作:移除根结点后,将list的最后一个项放置在根结点的位置上,然后根据二叉堆的属性进行go_down
操作(即根结点的项依次向下进行比较)
def go_down(self, index):
while index * 2 <= self.__size:
mc = self.find_min(index)
if self.__heap_list[index] > self.__heap_list[mc]:
self.__heap_list[index], self.__heap_list[mc] = self.__heap_list[mc], self.__heap_list[index]
index = mc
def find_min(self, index):
if index * 2 + 1 > self.__size:
return index * 2
else:
if self.__heap_list[index * 2] < self.__heap_list[index * 2 + 1]:
return index * 2
else:
return index * 2 + 1
def delete(self, data):
ret_val = self.__heap_list[1]
self.__heap_list[1] = self.__heap_list[self.__size]
self.__size = self.__size - 1
self.__heap_list.pop()
self.go_down(1)
return ret_val
建立二叉堆
两种想法:
1.可以将list直接进行排序,最低花费O(nlogn),得出的list肯定是个二叉堆
2.对于一个list的每一个项从左往右进行go_down
操作,时间复杂度O(n)
def delete(self, data):
ret_val = self.__heap_list[1]
self.__heap_list[1] = self.__heap_list[self.__size]
self.__size = self.__size - 1
self.__heap_list.pop()
self.go_down(1)
return ret_val
二叉堆完整实现
class BinaryHeap:
def __init__(self):
self.__heap_list = [0]
self.__size = 0
def go_up(self, index):
while index // 2 > 0:
if self.__heap_list[index] < self.__heap_list[index // 2]:
self.__heap_list[index], self.__heap_list[index // 2] = self.__heap_list[index // 2], self.__heap_list[index]
index = index // 2
def insert(self, data):
self.__heap_list.append(data)
self.__size = self.__size + 1
self.go_up(self.__size)
def go_down(self, index):
while index * 2 <= self.__size:
mc = self.find_min(index)
if self.__heap_list[index] > self.__heap_list[mc]:
self.__heap_list[index], self.__heap_list[mc] = self.__heap_list[mc], self.__heap_list[index]
index = mc
def find_min(self, index):
if index * 2 + 1 > self.__size:
return index * 2
else:
if self.__heap_list[index * 2] < self.__heap_list[index * 2 + 1]:
return index * 2
else:
return index * 2 + 1
def delete(self, data):
ret_val = self.__heap_list[1]
self.__heap_list[1] = self.__heap_list[self.__size]
self.__size = self.__size - 1
self.__heap_list.pop()
self.go_down(1)
return ret_val
def build_heap(self, alist):
index = len(alist) // 2
self.__size = len(alist)
self.__heap_list = [0] + alist[:]
while index > 0:
self.go_down(index)
index = index - 1
来源:oschina
链接:https://my.oschina.net/hongliang1205/blog/4305014