用堆实现优先级队列(Priority Queue)

1.优先级队列定义:

 优先级队列(priority queue) 是0个或多个元素的集合,每个元素都有一个优先权,对优先级队列执行的操作有

(1)查找

(2)插入一个新元素 

(3)删除 一般情况下,查找操作用来搜索优先权最大的元素,删除操作用来删除该元素 。

    对于优先权相同的元素,可按先进先出次序处理或按任意优先权进行。

2.优先级队列的实现方案

    优先级队列的实现既要兼顾成本,也要兼顾效率

    (1).第一种使用向量实现:

用堆实现优先级队列(Priority Queue)_第1张图片

                  由图可知,在使用插入操作时,时间复杂度为o(1),但是在getMax,需要遍历整个向量,找出最大的元素,

而delMax操作时却不仅要遍历向量找到最大元素,而且在摘抄它之后将所有元素顺序后移,这种时间复杂度是无法接受的。

(2).使用有序向量

用堆实现优先级队列(Priority Queue)_第2张图片

    在使用有序向量时,getMax操作和delMax操作都只有常数时间,但是在插入操作时,先要对其进行二分查找,找到插入的位置,然后在提前将它的后继依次后移,维护有序向量的有序性.这种方式时间复杂度太高,无法接受。

(3).使用列表

用堆实现优先级队列(Priority Queue)_第3张图片

在使用列表构建优先级队列时,insert操作只需在队尾将指针指向待插入元素。但是在getMax操作中,需要遍历整个列表。而在delMax操作时,先要找到最大值元素,然后在将前驱的指针指向后继,完成删除操作。所以这种方式时间复杂度较高。

(4)使用有序列表

用堆实现优先级队列(Priority Queue)_第4张图片

    在使用有序向量时,也面临着时间复杂度较高的情况。在进行insert操作时,需要找到待插入元素的前驱,然后将前驱的指针指向自己,自己的指针指向后继。

(5)使用BBST

用堆实现优先级队列(Priority Queue)_第5张图片

使用BBST构建优先级队列时,无论是插入,查找还是删除,都有非常优秀,但是优先级队列却不需要使用到全部的BBST。

(6)使用堆来实现优先级队列

堆是一种物理结构上用数组实现,逻辑结构为一颗完全二叉树的数据结构。堆的定义是父节点元素必定大于(小于)它的左孩子节点或者右孩子节点,(大于为大根堆,小于为小根堆)这样根节点元素则必然是整个堆的最大(最小)值。

以下是一个值为,1.2.3.4.5的小根堆的构成(因为我找到不到如何设置成大根堆.不过原理是一样的


用堆实现优先级队列(Priority Queue)_第6张图片

由图可知堆的逻辑结构和物理结构,下面给出具体的代码实现

3.具体实现

首先先给出它的insert操作

    def insert(self,value):
        self._arr.append(value) #将新值插入到堆尾
        self._index += 1        #index++ index代表了value的下标
        index=self._index
        if index % 2 == 0:
            parent = index // 2 - 1
        else:
            parent = index // 2 #获取index的父节点
        temp=self._arr[index]   #获取value的值

        #上滤
        while parent>=0:           #如果没超过根节点  也就是index的父节点最大只能为0号下标
            if   temp

 
  

getMax操作

    def getMax(self):
        if self._index == -1:   #如果_index为-1  则堆为空
            return
        self.__swap(0,self._index,self._arr)#不然交换堆顶元素和最后的元素
        maxValue=self._arr[self._index]  #交换后取得最后一个元素
        self.__remove()     #删除最后一个元素
        return maxValue     #返回最大值

 
  

remove操作

    def __remove(self):
        if self._index==-1: #如果_index为-1  则堆为空
            return
        self._arr.pop() #删除最后一个元素
        self._index-=1
        self.buildHeap(0,self._arr)#因为目前堆顶元素是未知的,所以要进行一次调整
        return

 
  

调整操作

    def buildHeap(self,index,_arr):
        if self._index==-1:    #如果堆里没有原始 则返回
            return
        temp=_arr[index]#temp代表index下标的值
        k=(index*2)+1  #k代表index的左子树
        lenth=len(_arr)-1
        while k<=lenth:
            if  k

 
  

测试结果

输入:

l=[11,2,3,4,5,6]
pq=PriorityQueue()
print('当前堆元素为',pq.get_arr())
print('获取最大值',pq.getMax())
print('当前堆元素为',pq.get_arr())
pq.insert(14)
print('当前堆元素为',pq.get_arr())
print('获取的最大值',pq.getMax())
print('获取的最大值',pq.getMax())
print('当前堆元素为',pq.get_arr())

输出:

当前堆元素为 [11, 5, 6, 4, 2, 3]
获取最大值 11
当前堆元素为 [6, 5, 3, 4, 2]
当前堆元素为 [14, 5, 6, 4, 2, 3]
获取的最大值 14

获取的最大值 6
当前堆元素为 [5, 4, 3, 2]


进程已结束,退出代码0
 
  

完整版代码

#优先级队列   2018-01-06
class PriorityQueue:
    _arr=[]
    _index=-1
    def __init__(self,arr=[]):
        self._arr=arr
        self._index=len(self._arr)-1#指向最后一个元素
        self.firstBuildHeap()
                        #index代表要进行向下调整的结点
    def buildHeap(self,index,_arr):
        if self._index==-1:    #如果堆里没有原始 则返回
            return
        temp=_arr[index]#temp代表index下标的值
        k=(index*2)+1  #k代表index的左子树
        lenth=len(_arr)-1
        while k<=lenth:
            if  k=0:
            self.buildHeap(index,self._arr)
            index-=1
    def get_arr(self):
        return self._arr

    def getMax(self):
        if self._index == -1:   #如果_index为-1  则堆为空
            return
        self.__swap(0,self._index,self._arr)#不然交换堆顶元素和最后的元素
        maxValue=self._arr[self._index]  #交换后取得最后一个元素
        self.__remove()     #删除最后一个元素
        return maxValue     #返回最大值

    def __remove(self):
        if self._index==-1: #如果_index为-1  则堆为空
            return
        self._arr.pop() #删除最后一个元素
        self._index-=1
        self.buildHeap(0,self._arr)#因为目前堆顶元素是未知的,所以要进行一次调整
        return

    def insert(self,value):
        self._arr.append(value) #将新值插入到堆尾
        self._index += 1        #index++ index代表了value的下标
        index=self._index
        if index % 2 == 0:
            parent = index // 2 - 1
        else:
            parent = index // 2 #获取index的父节点
        temp=self._arr[index]   #获取value的值

        #上滤
        while parent>=0:           #如果没超过根节点  也就是index的父节点最大只能为0号下标
            if   temp


你可能感兴趣的:(数据结构)