跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客我的书AI学习GitHub 精选镜像AI工具UI配色美学关于
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
C++算法

C++ STL 优先队列(priority_queue)原理与模拟实现

C++ 标准库中的优先队列基于堆实现,默认提供最大堆功能。其底层容器为 vector,通过向上调整和向下调整算法维护堆序性。核心操作包括 push、top、pop、size 和 empty,时间复杂度分别为 log n、1、log n、1 和 1。本文详细解析了优先队列的底层原理,并通过模拟实现展示了向上调整与向下调整的具体代码逻辑,帮助开发者深入理解其工作机制及性能特征。

落日余晖发布于 2026/3/25更新于 2026/10/2497 浏览
C++ STL 优先队列(priority_queue)原理与模拟实现

优先队列概述

priority_queue 是 C++ 标准模板库(STL)中一个非常实用的容器适配器,它基于堆(Heap)数据结构实现。默认情况下,它是一个最大堆,即每次取出的都是当前集合中优先级最高的元素。

在实际开发中,无论是算法竞赛中的贪心策略,还是操作系统调度、实时交易系统的任务处理,只要涉及'按优先级排序'的需求,优先队列都是首选方案。

底层结构与特性

优先队列的底层容器默认是 vector。选择连续内存结构不仅适合堆的随机访问需求,还能带来更好的缓存命中率。虽然头文件包含在 <queue> 中,但它的行为更接近于一种特殊的队列——只允许在队尾插入,在队首(堆顶)访问和删除。

核心特点:

  • 存储方式:数组形式存储的完全二叉树。
  • 默认行为:大顶堆(最大值在顶部)。
  • 自定义小顶堆:需传入比较器 greater<int>。
  • 操作限制:只能访问堆顶元素,无法遍历中间节点。
  • 时间复杂度:访问 O(1),插入/删除 O(log n)。

文章配图

API 使用指南

初始化

支持默认构造或范围初始化:

// 默认初始化
priority_queue<int> pq;

// 范围初始化(例如从数组)
int arr[] = {1, 5, 3};
priority_queue<int> pq2(arr, arr + 3);
基本操作
  • 插入元素:push(val),自动调整堆结构,O(log n)。
  • 访问堆顶:top(),返回最高优先级元素,不删除,O(1)。
  • 删除堆顶:pop(),移除当前最大值,并重新调整堆,O(log n)。
  • 判断空:empty(),若为空返回 true。
  • 获取大小:size(),返回当前元素个数。
V.push(val);      // 插入
V.top();          // 查看
V.pop();          // 弹出
V.size();         // 大小
V.empty();        // 判空

文章配图

深入底层:模拟实现

理解优先队列的最佳方式是亲手实现它。既然底层是 vector,我们只需要封装一层逻辑,维护堆的性质即可。

类模板定义
template<class T, class container = std::vector<T>>
class priority_queue {
public:
    // 构造函数通常可省略,依赖 vector 默认构造
private:
    container x; // 底层容器
};
插入逻辑:向上调整

插入时,先将元素追加到尾部,然后从该位置开始向上调整,直到满足父节点大于子节点的大顶堆性质。

void push(const T& value) {
    x.push_back(value);
    shiftUp(x.size() - 1); // 向上调整
}

void shiftUp(int child) {
    while (child > 0) {
        int parent = (child - 1) / 2;
        if (x[child] > x[parent]) {
            std::swap(x[child], x[parent]);
            child = parent;
        } else {
            break; // 已满足堆性质
        }
    }
}

文章配图

删除逻辑:向下调整

删除堆顶元素不能直接删,否则会导致空缺。标准做法是将堆顶与最后一个元素交换,删除尾部,然后从根节点开始向下调整。

void pop() {
    if (!x.empty()) {
        std::swap(x[0], x.back());
        x.pop_back();
        shiftDown(0); // 向下调整
    }
}

void shiftDown(int parent) {
    int child = 2 * parent + 1; // 左孩子
    while (child < x.size()) {
        // 如果右孩子存在且比左孩子大,选右孩子
        if (child + 1 < x.size() && x[child + 1] > x[child]) {
            child++;
        }
        // 如果父节点小于较大的子节点,则交换
        if (x[parent] < x[child]) {
            std::swap(x[parent], x[child]);
            parent = child;
            child = 2 * parent + 1;
        } else {
            break;
        }
    }
}

文章配图

完整测试示例
void test_priority_queue() {
    std::priority_queue<int> pq;
    
    // 插入一组数据
    for (int val : {10, 15, 5, 20, 0, 25}) {
        pq.push(val);
    }

    // 输出堆顶(最大值)
    std::cout << "Top: " << pq.top() << std::endl;
    
    // 弹出堆顶
    pq.pop();
    std::cout << "New Top: " << pq.top() << std::endl;
    
    // 检查是否为空
    std::cout << "Empty: " << pq.empty() << std::endl;
}

文章配图

目录

  1. 优先队列概述
  2. 底层结构与特性
  3. API 使用指南
  4. 初始化
  5. 基本操作
  6. 深入底层:模拟实现
  7. 类模板定义
  8. 插入逻辑:向上调整
  9. 删除逻辑:向下调整
  10. 完整测试示例

更多推荐文章

查看全部
  • Python 安装与语法基础入门教程
  • Arduino 环境搭建与智能家居入门实战指南
  • Vue3 核心语法与状态管理学习笔记
  • 学生如何申请并使用 GitHub Copilot 进行编程实践
  • 快速排序算法发展历程及三路划分、内省排序实现
  • libwebkit2gtk-4.1-0 安装依赖处理:Ubuntu 22.04 场景解析
  • 宝塔面板 Docker 部署青龙面板教程
  • SpringBoot 网约车司机预约系统设计与实现
  • Agentic AI 与传统 AIGC 的区别及核心概念解析
  • Windows 系统 Visual C++ 运行库全生命周期管理方案
  • Java 排序实战:Arrays.sort 与 Collections.sort 用法解析
  • Docker 安装及基础操作指南
  • Rust 异步微服务架构最佳实践与常见反模式
  • 基于 Leaflet 和天地图的免费运动场所 WebGIS 可视化
  • Java 中的 char、String、StringBuilder 与 StringBuffer 详解
  • Java 字符串转整数与拼接实战指南
  • 2026 年 3 月全球大模型全景:国产登顶、百万上下文与智能体爆发
  • C++ 继承基础:概念定义、访问权限与默认成员函数
  • STL-thumbnail:Windows 资源管理器 STL 文件预览方案
  • 基于 Java 与 Leaflet 的湖南省道路长度 WebGIS 系统构建

相关免费在线工具

  • 加密/解密文本

    使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online

  • Gemini 图片去水印

    基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online

  • Markdown转HTML

    将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online

  • HTML转Markdown

    将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online