优先队列详解

优先队列是计算机科学中的一种抽象数据类型,它是一种队列:元素拥有优先级,优先级最高的元素最先得到服务;优先级相同的元素按照在集合中的顺序得到服务。优先队列有两种主要的实现方法:堆和二叉搜索树。

简单来说,优先队列是一种特殊的队列,不同于先进先出的普通队列,优先队列中的每个元素都有一定的优先级,优先级最高的元素最先出队。故而优先队列非常适合用来解决一些涉及元素优先级的问题。

在C++的STL中,priority_queue是实现优先队列的一个类模板。priority_queue中的元素默认按照大顶堆的方式进行排列,即出队顺序是优先级由高到低。

下面我们来介绍三个使用优先队列解决的典型问题:

1. 第K大元素查询

给定一个未排序的数组,找出第K大的元素。例如给定数组[3,2,1,5,6,4]和k = 2,返回5.

代码实现及注释:

cpp 复制代码
#include <queue>
#include <vector>
#include <iostream>
using namespace std;

int findKthLargest(vector<int>& nums, int k) {
    // 创建一个小顶堆,当堆的大小超过k时,弹出堆顶元素
    priority_queue<int, vector<int>, greater<int>> pq;
    for (int num : nums) {
        pq.push(num);
        if (pq.size() > k) {
            pq.pop();
        }
    }
    // 当所有元素都已入堆后,堆顶元素就是数组中第k大的元素
    return pq.top();
}

int main() {
    vector<int> nums = {3,2,1,5,6,4};
    int k = 2;
    cout << "The Kth largest number is: " << findKthLargest(nums, k) << endl;
    
    return 0;
}

2. 合并K个排序链表

给定K个已排序的链表,将它们合并为一个新的排序链表。

代码实现及注释:

cpp 复制代码
#include <queue>
#include <vector>
#include <iostream>
using namespace std;

struct ListNode {
    int val;
    ListNode *next;
    ListNode() : val(0), next(NULL) {}
};

struct compare {
    bool operator()(ListNode* l1, ListNode* l2) {
        return l1->val > l2->val;
    }
};

ListNode* mergeKLists(vector<ListNode*>& lists) {
    // 创建一个小顶堆,把所有链表的头节点放入堆中
    priority_queue<ListNode*, vector<ListNode*>, compare> pq;
    for (ListNode* list : lists) {
        if (list) {
            pq.push(list);
        }
    }

    ListNode *dummy = new ListNode();
    ListNode *cur = dummy;

    while (!pq.empty()) {
        // 取出当前最小的节点,存入新链表中
        ListNode* node = pq.top(); 
        pq.pop();
        cur->next = node;
        cur = node;

        if (node->next) {
            pq.push(node->next); // 将当前最小节点的后续节点放入优先队列中
        }
    }

    return dummy->next; // 返回去掉哑节点头的链表
}

3. 数据流的中位数

给定一个数据流,寻找数据流的中位数。例如,数据流[2,3,4]的中位数是3,数据流[2,3]的中位数是2.5.

代码实现及注释:

cpp 复制代码
#include <queue>
using namespace std;

class MedianFinder {
public:
    /** initialize your data structure here. */
    MedianFinder() {

    }

    void addNum(int num) {
        left.push(num);
        right.push(-left.top());
        left.pop();

        if (left.size() < right.size()) {
            left.push(-right.top());
            right.pop();
        }
    }

    double findMedian() {
        if (left.size() > right.size()) {
            return left.top();
        } else {
            return (left.top() - right.top()) / 2.0;
        }
    }

private:
    // 左侧大顶堆,右侧小顶堆,保证大顶堆的所有元素都小于小顶堆,且大顶堆的元素可以多一个
    priority_queue<int> left;
    priority_queue<int> right;
};

这三个案例展示了优先队列在不同问题中的应用,包括寻找第K大元素,合并排序链表,以及寻找数据流的中位数。请记住,优先队列主要用于处理涉及元素优先级的问题。

如果你想更深入地了解人工智能的其他方面,比如机器学习、深度学习、自然语言处理等等,也可以点击这个链接,我按照如下图所示的学习路线为大家整理了100多G的学习资源,基本涵盖了人工智能学习的所有内容,包括了目前人工智能领域最新顶会论文合集和丰富详细的项目实战资料,可以帮助你入门和进阶。

链接: 人工智能交流群(大量资料)

相关推荐
槿花Hibiscus1 小时前
C++基础:Pimpl设计模式的实现
c++·设计模式
shinelord明2 小时前
【再谈设计模式】建造者模式~对象构建的指挥家
开发语言·数据结构·设计模式
黑不拉几的小白兔2 小时前
PTA部分题目C++重练
开发语言·c++·算法
写bug的小屁孩2 小时前
websocket身份验证
开发语言·网络·c++·qt·websocket·网络协议·qt6.3
chordful2 小时前
Leetcode热题100-32 最长有效括号
c++·算法·leetcode·动态规划
材料苦逼不会梦到计算机白富美2 小时前
线性DP 区间DP C++
开发语言·c++·动态规划
Romanticroom3 小时前
计算机23级数据结构上机实验(第3-4周)
数据结构·算法
白藏y3 小时前
数据结构——归并排序
数据结构·算法·排序算法
ahadee3 小时前
蓝桥杯每日真题 - 第12天
c++·vscode·算法·蓝桥杯
vortex53 小时前
解决 VSCode 中 C/C++ 编码乱码问题的两种方法
c语言·c++·vscode