优先队列基础知识

0. 简介

最近在自己编写一些小的算法的时候,深感自己的算法过于臃肿。碰巧Datawhale在新的一期组队学习中组织了数据结构与算法的课程学习。于是就参加了,再次感谢Datawhale~~

首先跟大家分享一下两个自己感觉比较好的学习资料,一个是 算法通关手册 ,也是Datawhale在本次组队学习中的学习资料;一个是B站上的视频 【北京大学】数据结构与算法Python版(完整版),老师讲的特别棒(也难得有Python版的数据结构课程,哈哈~)。

1. 优先队列简介

优先队列(Priority Queue):一种特殊的队列。在优先队列中,元素被赋予优先级,当访问队列元素时,具有最高优先级的元素最先删除。

优先队列的出队顺序跟入队顺序无关,优先队列是按照元素的优先级来决定出队顺序的。优先级高的元素优先出队,优先级低的元素后出队。优先队列符合 最高级先出(First in, Largest out) 的规则。

2. 优先队列的储存形式

优先队列的储存形式主要有以下三种。这三种存储方式在出队和入队操作时分布有着不同的时间复杂度:

  • 数组(顺序存储)实现优先队列:入队操作直接插入到数组队尾,时间复杂度为 O ( 1 ) O(1) O(1)。出队操作需要遍历整个数组,找到优先级最高的元素,返回并删除该元素,时间复杂度为 O ( n ) O(n) O(n)
  • 链表(链式存储)实现优先队列:链表中的元素按照优先级排序,入队操作需要为待插入元素创建节点,并在链表中找到合适的插入位置,时间复杂度为 O ( n ) O(n) O(n)。出队操作直接返回链表队头元素,并删除队头元素,时间复杂度为 O ( 1 ) O(1) O(1)
  • 二叉堆结构实现优先队列:构建一个二叉堆结构,二叉堆按照优先级进行排序。入队操作就是将元素插入到二叉堆中合适位置,时间复杂度为 O ( l o g 2 n ) O(log_2n) O(log2n)。吹对操作则返回二叉堆中优先级最大节点并删除,时间复杂度也是 O ( l o g 2 n ) O(log_2n) O(log2n)

Python 中的 heapq 模块提供了优先队列算法来实现 二叉堆结构实现优先队列 。函数 heapq.heappush() 用于在队列 queue 上插入一个元素。heapq.heappop() 用于在队列 queue 上删除一个元素。需要注意的是:heapq.heappop() 函数总是返回「最小的」的元素。所以我们在使用 heapq.heappush() 时,将优先级设置为负数,这样就使得元素可以按照优先级从高到低排序, 这个跟普通的按优先级从低到高排序的堆排序恰巧相反。这样做的目的是为了 heapq.heappop() 每次弹出的元素都是优先级最高的元素。

import heapq

class PriorityQueue:
    def __init__(self):
        self.queue = []
        self.index = 0

    def push(self, item, priority):
        heapq.heappush(self.queue, (-priority, self.index, item))
        self.index += 1

    def pop(self):
        return heapq.heappop(self.queue)[-1]

3. 优先队列的应用

239. 滑动窗口最大值 - 力扣(LeetCode)

给定一个整数数组 nums,再给定一个整数 k,表示为大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。我们只能看到滑动窗口内的 k 个数字,滑动窗口每次只能向右移动一位。要求:返回滑动窗口中的最大值。

算法通关手册 给出了相应的解题思路和代码实现

  • 初始的时候将前 k 个元素加入优先队列的二叉堆中。存入优先队列的是数组值和索引的元组。优先队列将数组值作为优先级。
  • 然后滑动窗口从第 k 个元素开始遍历,将当前数组值和索引的元组插入到二叉堆中。
  • 当二叉堆堆顶元素的索引已经不在滑动窗口的范围中时,即 q[0][1] <= i - k 时,不断删除堆顶元素,直到最大值元素的索引在滑动窗口的范围中。
  • 将最大值加入到答案数组中,继续滑动。
  • 最后遍历完输出答案数组。
class Solution:
    def maxSlidingWindow(self, nums: List[int], k: int) -> List[int]:
        size = len(nums)
        q = [(-nums[i], i) for i in range(k)]
        heapq.heapify(q)
        res = [-q[0][0]]

        for i in range(k, size):
            heapq.heappush(q, (-nums[i], i))
            while q[0][1] <= i - k:
                heapq.heappop(q)
            res.append(-q[0][0])
        return res

你可能感兴趣的:(数据结构与算法,数据结构,算法,队列,优先队列,python)