C++中priority_queue的实现

 更新时间:2026年03月27日 09:51:21   作者:Ralph_Y  
priority_queue是C++ STL中的适配器容器,基于堆结构实现,本文介绍C++中priority_queue的实现,具有一定的参考价值,感兴趣的可以了解一下

一、priority_queue 核心定义

std::priority_queue(优先队列)是 C++ STL 中的适配器容器(基于其他容器实现),本质是一个「堆结构」——队列中的元素会按照优先级自动排序,而非按插入顺序。

  • 核心特性:每次访问/弹出的都是优先级最高的元素(默认是最大值,可自定义为最小值);
  • 底层实现:默认基于 std::vector,也可指定 std::deque(不支持 std::list,因为堆需要随机访问);
  • 头文件:必须包含 <queue>

二、基本用法(默认大顶堆)

1. 初始化与核心操作

#include <iostream>
#include <queue> // 必须包含
using namespace std;
int main() {
    // 1. 初始化:默认是大顶堆(最大值优先)
    priority_queue<int> pq;
    // 2. 插入元素(push):O(log n) 复杂度
    pq.push(3);
    pq.push(1);
    pq.push(5);
    pq.push(2);
    // 3. 访问队首(top):返回优先级最高的元素(最大值)
    cout << "队首元素(最大值):" << pq.top() << endl; // 输出:5
    // 4. 弹出队首(pop):删除优先级最高的元素,O(log n) 复杂度
    pq.pop();
    cout << "弹出后队首:" << pq.top() << endl; // 输出:3
    // 5. 判空(empty)、大小(size)
    cout << "是否为空:" << (pq.empty() ? "是" : "否") << endl; // 输出:否
    cout << "元素个数:" << pq.size() << endl; // 输出:3
    // 6. 遍历(无迭代器,需弹出所有元素)
    while (!pq.empty()) {
        cout << pq.top() << " "; // 输出:3 2 1
        pq.pop();
    }
    return 0;
}

2. 关键说明

  • top():仅返回队首元素,不删除;pop():仅删除队首元素,无返回值(需先 top()pop());
  • clear() 成员函数:清空优先队列需手动弹出所有元素,或赋值空队列(pq = priority_queue<int>(););
  • 不支持随机访问:无法直接访问中间元素,只能通过 top() 访问队首。

三、自定义优先级(小顶堆/自定义规则)

默认的 priority_queue 是「大顶堆」(最大值优先),可通过以下方式修改优先级:

1. 实现小顶堆(最小值优先)

方式1:指定比较函数 greater<T>

#include <iostream>
#include <queue>
#include <vector> // 显式指定底层容器
using namespace std;

int main() {
    // 模板参数:<元素类型, 底层容器类型, 比较函数>
    priority_queue<int, vector<int>, greater<int>> pq;

    pq.push(3);
    pq.push(1);
    pq.push(5);
    pq.push(2);

    cout << "小顶堆队首(最小值):" << pq.top() << endl; // 输出:1
    pq.pop();
    cout << "弹出后队首:" << pq.top() << endl; // 输出:2

    return 0;
}

方式2:对元素取反(适用于简单类型)

// 插入时取反,弹出时再取反,模拟小顶堆
priority_queue<int> pq;
pq.push(-3);
pq.push(-1);
pq.push(-5);
pq.push(-2);
cout << "模拟小顶堆队首:" << -pq.top() << endl; // 输出:1

2. 自定义结构体/类的优先级

需重载比较运算符(operator<),或自定义比较函数。

示例:结构体按指定字段排序

#include <iostream>
#include <queue>
#include <string>
using namespace std;

// 定义结构体:存储学生姓名和分数
struct Student {
    string name;
    int score;

    // 重载 < 运算符(注意:优先队列用 < 比较,且规则与直觉相反)
    // 需求:分数高的优先级高(大顶堆)
    bool operator<(const Student& other) const {
        // 若 this->score < other.score,则 other 优先级更高
        return score < other.score;
    }
};

int main() {
    priority_queue<Student> pq;
    pq.push({"Alice", 85});
    pq.push({"Bob", 92});
    pq.push({"Charlie", 78});

    // 输出优先级最高的元素(分数最高的Bob)
    cout << "最高分:" << pq.top().name << " " << pq.top().score << endl; // Bob 92
    pq.pop();
    cout << "次高分:" << pq.top().name << " " << pq.top().score << endl; // Alice 85

    return 0;
}

自定义比较函数(适用于复杂规则)

#include <iostream>
#include <queue>
#include <string>
#include <functional> // 需包含(for function)
using namespace std;

struct Student {
    string name;
    int score;
};

// 自定义比较函数:分数低的优先级高(小顶堆)
struct CompareStudent {
    bool operator()(const Student& a, const Student& b) {
        return a.score > b.score; // 与小顶堆的 greater 逻辑一致
    }
};

int main() {
    priority_queue<Student, vector<Student>, CompareStudent> pq;
    pq.push({"Alice", 85});
    pq.push({"Bob", 92});
    pq.push({"Charlie", 78});

    cout << "最低分:" << pq.top().name << " " << pq.top().score << endl; // Charlie 78

    return 0;
}

四、底层原理:堆结构

priority_queue 的核心是二叉堆(完全二叉树),所有操作均基于堆的特性:

  1. 插入(push):将元素添加到堆尾,然后「上浮(sift up)」调整堆,确保父节点优先级高于子节点(O(log n));
  2. 弹出(pop):将堆顶元素与堆尾元素交换,删除堆尾,然后「下沉(sift down)」调整堆(O(log n));
  3. 访问队首(top):直接返回堆顶元素(O(1))。

五、常见应用场景

  1. Top K 问题:如找数组中前 K 大/前 K 小的元素(用小顶堆存前 K 大,大顶堆存前 K 小);
    // 示例:找数组中前3大的元素
    vector<int> nums = {5, 2, 9, 1, 7, 6, 8};
    priority_queue<int, vector<int>, greater<int>> pq; // 小顶堆
    for (int num : nums) {
        pq.push(num);
        if (pq.size() > 3) pq.pop(); // 保持堆大小为3
    }
    // 此时堆中是前3大的元素(7,8,9),但顺序是从小到大
    
  2. 贪心算法:如任务调度、哈夫曼编码、最短路径(Dijkstra 算法);
  3. 实时排序:需频繁获取最大值/最小值的场景(如事件优先级处理)。

六、注意事项

  1. 底层容器限制:只能用支持随机访问的容器(vector/deque),不能用 list(无随机访问);
  2. 比较函数规则
    • 默认 less<T>:大顶堆(a < b 则 b 优先级高);
    • greater<T>:小顶堆(a > b 则 b 优先级高);
  3. 性能:插入/弹出为 O(log n),访问队首为 O(1),遍历需弹出所有元素(O(n log n));
  4. 线程安全:无内置线程安全,多线程需手动加锁。

总结

核心特性说明
排序规则默认大顶堆,可自定义为小顶堆/自定义规则
核心操作push(插入)、top(查队首)、pop(删队首)
时间复杂度push/pop: O(log n),top: O(1)
底层容器默认 vector,可指定 deque
适用场景Top K、贪心算法、实时优先级处理

priority_queue 是 C++ 中处理「优先级排序」的核心容器,重点掌握自定义优先级的两种方式(greater<T>/自定义比较函数),以及 Top K 问题的经典用法。

到此这篇关于C++中priority_queue的实现的文章就介绍到这了,更多相关C++ priority_queue内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • VScode+cuda编程常见环境问题的解决

    VScode+cuda编程常见环境问题的解决

    本文主要介绍了VScode+cuda编程常见环境问题的解决,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-02-02
  • 判断指定的进程或程序是否存在方法小结(vc等)

    判断指定的进程或程序是否存在方法小结(vc等)

    VC判断进程是否存在?比如我想知道记事本是否运行,要用到哪些函数等实例,需要的朋友可以参考下
    2013-01-01
  • C++获取特定进程CPU使用率的实现代码

    C++获取特定进程CPU使用率的实现代码

    写一个小程序在后台记录每个进程的CPU使用情况,揪出锁屏后占用CPU的进程,于是自己写了一个C++类CPUusage,方便地监视不同进程的CPU占用情况。本人编程还只是个新手,如有问题请多多指教
    2019-04-04
  • C++ 多态虚函数的底层原理深入理解

    C++ 多态虚函数的底层原理深入理解

    这篇文章主要介绍了C++ 多态虚函数的底层原理深入理解,多态是在不同继承关系的类对象,去调用同一函数,产生了不同的行为,通常是父类调用子类的重写函数,在C++中就是 父类指针指向子类对象,此时父类指针的向下引用就可以实现多态
    2022-08-08
  • 详解C++编程中向函数传递引用参数的用法

    详解C++编程中向函数传递引用参数的用法

    这篇文章主要介绍了详解C++编程中向函数传递引用参数的用法,包括使函数返回引用类型以及对指针的引用,需要的朋友可以参考下
    2016-01-01
  • C++中用new创建二维数组和指针数组实例代码

    C++中用new创建二维数组和指针数组实例代码

    这篇文章主要介绍了C++中用new创建二维数组和指针数组实例代码,非常不错,具有参考借鉴价值,需要的朋友参考下
    2017-03-03
  • C语言初学者代码中的常见错误与问题

    C语言初学者代码中的常见错误与问题

    C语言初学者犯过的很多错误都非常典型,在初学者中非常普遍,于是整理了一下,应该对其他初学者有借鉴意义
    2013-11-11
  • C语言container of()函数案例详解

    C语言container of()函数案例详解

    这篇文章主要介绍了C语言container of()函数案例详解,本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下
    2021-08-08
  • C语言中break与continue的用法和区别详解

    C语言中break与continue的用法和区别详解

    当我们使用while或for循环时,如果想提前结束循环(在不满足结束条件的情况下结束循环),可以使用break或continue关键字,这篇文章主要给大家介绍了关于C语言中break与continue的用法和区别的相关资料,需要的朋友可以参考下
    2021-10-10
  • 一文带你了解C++中的右值引用与移动语义

    一文带你了解C++中的右值引用与移动语义

    本篇文章主要为大家详细介绍了C++中的右值引用与移动语义的相关知识,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2023-03-03

最新评论