zoukankan      html  css  js  c++  java
  • 最小堆实现优先队列:Python实现

    最小堆实现优先队列:Python实现

    堆是一种数据结构,因为Heapsort而被提出。除了堆排序,“堆”这种数据结构还可以用于优先队列的实现。

    堆首先是一个完全二叉树:它除了最底层之外,树的每一层的都是满的,且最底层中的节点处于左边,相互之间没有“跳变”;其次,堆有次序属性:每个节点中的数据项都大于或者等于其子女的数据项(如果是记录,则这些记录中的某个关键域必须满足这一属性)。 当然,这是指大顶堆,小顶堆则是父节点比子节点都要小。

    所谓队列,就是一个FIFO表(first in, first out)。优先队列,就是在队列的基础上,每个元素加一个优先级,last in的元素可能会first out,这就是优先级在起作用。

    我想实现这样一个优先队列:

      元素为整数

      元素值小的优先级反而大

      有入队操作,每次进入一个元素

      出队操作,也行每次一个元素

    那么,我的小根堆Heap应该这样考虑:

      每当插入元素时,在原有Heap的最后一个叶子节点后面插入新元素val,并持续比较val和其父节点的值之间是否满足堆的次序属性,直到满足

      每当删除元素时,删除的是值最小的元素,也就是根结点root,则将root和最后一个叶子节点lastleaf互换,然后删除交换后的new_lastleaf ,并从new_root开始调整堆,使满足堆的次序属性。

    这样一来,代码就不难写出:

    #coding:utf8#author:HaxtraZ#description:优先队列,用堆实现#修改自《算法导论》2nd EditionclassZHeap:def __init__(self, item=[]):# 初始化。item为数组self.items = item
            self.heapsize = len(self.items)def LEFT(self, i):return2* i +1def RIGHT(self, i):return2* i +2def PARENT(self, i):return(i -1)/2def MIN_HEAPIFY(self, i):# 最小堆化:使以i为根的子树成为最小堆
            l =self.LEFT(i)
            r =self.RIGHT(i)if l <self.heapsize andself.items[l]<self.items[i]:
                smallest = l
            else:
                smallest = i
    
            if r <self.heapsize andself.items[r]<self.items[smallest]:
                smallest = r
    
            if smallest != i:self.items[i],self.items[smallest]=self.items[smallest],self.items[i]self.MIN_HEAPIFY(smallest)def INSERT(self, val):# 插入一个值val,并且调整使满足堆结构self.items.append(val)
            idx = len(self.items)-1
            parIdx =self.PARENT(idx)while parIdx >=0:ifself.items[parIdx]>self.items[idx]:self.items[parIdx],self.items[idx]=self.items[idx],self.items[parIdx]
                    idx = parIdx
                    parIdx =self.PARENT(parIdx)else:breakself.heapsize +=1def DELETE(self):last= len(self.items)-1iflast<0:# 堆为空returnNone# else:self.items[0],self.items[last]=self.items[last],self.items[0]
            val =self.items.pop()self.heapsize -=1self.MIN_HEAPIFY(0)return val
    
    
        def BUILD_MIN_HEAP(self):# 建立最小堆, O(nlog(n))
            i =self.PARENT(len(self.items)-1)while i >=0:self.MIN_HEAPIFY(i)
                i -=1def SHOW(self):printself.items
    
    
    classZPriorityQ(ZHeap):def __init__(self, item=[]):ZHeap.__init__(self, item)def enQ(self, val):ZHeap.INSERT(self, val)def deQ(self):
            val =ZHeap.DELETE(self)return val
    
    
    a =[1,3,2,4,8,6,22,9]
    pq =ZPriorityQ()
    n = len(a)for i in range(n):
        pq.enQ(a[i])
        pq.SHOW()for i in range(n):
        pq.deQ()
        pq.SHOW()

      其中,ZHeap表示小根堆,ZPriorityQ表示优先队列,deQ表示退队,enQ表示入队。

      我们发现以下结论:大根堆用于升序排序,小根堆用于降序排序。

      为什么用堆来实现优先队列?原因只有一个:复杂度低。

        如果使用列表(存放在list中),插入为O(1),删除为O(n);

        如果使用按照优先级排好序的有序列表,插入和线性插入排序一样,O(n),删除则为O(1)

      使用堆的时候,无论你删除还是插入,都是O(lg n)时间复杂度,对于插入和删除都比较频繁的操作来讲,这是最好不过的了。

      如果认为有不正确的地方欢迎拍砖。

  • 相关阅读:
    java 异常java.lang.UnsupportedOperationException
    转载RabbitMQ入门(6)--远程调用
    转载RabbitMQ入门(5)--主题
    转载RabbitMQ入门(4)--路由
    转载RabbitMQ入门(3)--发布和订阅
    转载RabbitMQ入门(2)--工作队列
    转载RabbitMQ入门(1)--介绍
    转载:浅析Java中的final关键字
    Java NIO Channel通道
    Java NIO Buffer缓冲区
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/3279198.html
Copyright © 2011-2022 走看看