优先队列详解

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

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

在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的学习资源,基本涵盖了人工智能学习的所有内容,包括了目前人工智能领域最新顶会论文合集和丰富详细的项目实战资料,可以帮助你入门和进阶。

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

相关推荐
宵时待雨4 分钟前
linux笔记归纳25:多路转接epoll
linux·服务器·网络·c++
Frank_refuel17 分钟前
【C++项目】手撕JRpc框架(单机怎么优化到分布式思想)
开发语言·c++
ShineWinsu26 分钟前
对于Redis:Hash类型的解析
c++·redis·分布式·缓存·面试·hash·哈希表
wuminyu30 分钟前
JEP491中synchronized关键字引发的平台线程钉住解决方法简介
java·linux·c语言·jvm·c++
All for pursuit.39 分钟前
【贪心-4】581.最短无序连续子数组
数据结构·c++·算法·leetcode
无名猿1 小时前
list 与 forward_list:链表真的比 vector 快吗
c++·性能优化·stl·内存管理·标准库
笑鸿的学习笔记1 小时前
C++笔记之SIMD与SSE指令集
开发语言·c++·笔记
汉克老师2 小时前
GESP2026年9月认证C++一级( 第二部分判断题(1~10题)精讲
c++·gesp·小学生·学c++编程
mmmmath_32 小时前
LeetCode.020.有效的括号
数据结构·算法·leetcode
垆边人似月.2 小时前
华为机考题:字符个数统计
数据结构·算法·华为