优先队列详解

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

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

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

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

相关推荐
石头猫灯19 小时前
WordPress wp2shell 漏洞链完整拆解流程
网络·数据结构·安全·web安全
别动我齐刘海20 小时前
机器人运动控制学习2——基础进阶
c++·人工智能·神经网络·学习·目标检测·机器学习·机器人
傻啦嘿哟20 小时前
英雄联盟皮肤爬虫:爬取全皮肤价格与特效,做比价工具
java·c++·爬虫
码匠许师傅21 小时前
【C++ 面试真题】24. 聊聊 C++ 的时间日期处理
java·c++·面试
闻道且行之21 小时前
图片处理助手|泊松融合原理 + C++ 工程实现,seamlessClone 三模式一次讲透
数据库·c++·人工智能·opencv
莫浅子1 天前
day01-USB架构与枚举
c++·单片机·嵌入式驱动
小欣加油1 天前
leetcode3069 将元素分配到两个数组中I
数据结构·c++·算法·leetcode·职场和发展
不会代码的小猴1 天前
7. JSON
开发语言·c++·笔记·qt·算法·json
沫璃染墨1 天前
《Qt从零入门系列(六):信号与槽进阶——从多种连接方式到Lambda表达式》
开发语言·c++·qt·代码规范·设计规范·qt5
小小龙学IT1 天前
ZeroMQ(libzmq)开源消息库深度解析:brokerless 时代的轻量消息内核
c++·开源