博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
最小堆实现优先队列:Python实现
阅读量:5153 次
发布时间:2019-06-13

本文共 3046 字,大约阅读时间需要 10 分钟。

堆是一种数据结构,因为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 Editionclass ZHeap:    def __init__(self, item=[]):        # 初始化。item为数组        self.items = item        self.heapsize = len(self.items)    def LEFT(self, i):        return 2 * i + 1    def RIGHT(self, i):        return 2 * i + 2    def PARENT(self, i):        return (i - 1) / 2    def MIN_HEAPIFY(self, i):        # 最小堆化:使以i为根的子树成为最小堆        l = self.LEFT(i)        r = self.RIGHT(i)        if l < self.heapsize and self.items[l] < self.items[i]:            smallest = l        else:            smallest = i        if r < self.heapsize and self.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:            if self.items[parIdx] > self.items[idx]:                self.items[parIdx], self.items[idx] = self.items[idx], self.items[parIdx]                idx = parIdx                parIdx = self.PARENT(parIdx)            else:                break        self.heapsize += 1    def DELETE(self):        last = len(self.items) - 1        if last < 0:            # 堆为空            return None        # else:        self.items[0], self.items[last] = self.items[last], self.items[0]        val = self.items.pop()        self.heapsize -= 1        self.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 -= 1    def SHOW(self):        print self.itemsclass ZPriorityQ(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 vala = [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)时间复杂度,对于插入和删除都比较频繁的操作来讲,这是最好不过的了。

 

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

转载于:https://www.cnblogs.com/zjutzz/p/3278790.html

你可能感兴趣的文章
一些php文件函数
查看>>
有关快速幂取模
查看>>
Linux运维必备工具
查看>>
字符串的查找删除
查看>>
NOI2018垫底记
查看>>
快速切题 poj 1002 487-3279 按规则处理 模拟 难度:0
查看>>
Codeforces Round #277 (Div. 2)
查看>>
【更新】智能手机批量添加联系人
查看>>
NYOJ-128前缀式计算
查看>>
淡定,啊。数据唯一性
查看>>
深入理解 JavaScript 事件循环(一)— event loop
查看>>
Hive(7)-基本查询语句
查看>>
注意java的对象引用
查看>>
C++ 面向对象 类成员函数this指针
查看>>
NSPredicate的使用,超级强大
查看>>
自动分割mp3等音频视频文件的脚本
查看>>
判断字符串是否为空的注意事项
查看>>
布兰诗歌
查看>>
js编码
查看>>
Pycharm Error loading package list:Status: 403错误解决方法
查看>>