0

0

如何用c++实现一个优先队列 priority_queue和堆【数据结构】

尼克

尼克

发布时间:2025-12-23 12:51:21

|

215人浏览过

|

来源于php中文网

原创

C++中priority_queue默认为最大堆,基于vector和堆算法实现;最小堆需指定greater比较器;还可用make_heap等底层函数或手动实现堆结构。

如何用c++实现一个优先队列 priority_queue和堆【数据结构】

在 C++ 中,priority_queue 是标准模板库(STL)提供的容器适配器,底层默认基于 最大堆(max-heap) 实现,使用 std::vector 作为存储结构,并通过 std::make_heapstd::push_heapstd::pop_heap 等算法维护堆性质。你可以直接使用它,也可以手动实现一个最小堆/最大堆来深入理解原理。

用 STL priority_queue 快速实现优先队列

这是最常用、最安全的方式,适用于绝大多数场景:

  • 默认是最大堆:顶部元素最大(top() 返回最大值)
  • 要改成最小堆,需指定比较器:priority_queue, greater>
  • 支持的操作:`push()`、`top()`、`pop()`、`empty()`、`size()`,时间复杂度均为 O(log n)

示例代码:

#include 
#include 
using namespace std;

int main() {
    // 最大堆(默认)
    priority_queue maxQ;
    maxQ.push(3); maxQ.push(1); maxQ.push(4);
    cout << maxQ.top() << endl; // 输出 4

    // 最小堆
    priority_queue, greater> minQ;
    minQ.push(3); minQ.push(1); minQ.push(4);
    cout << minQ.top() << endl; // 输出 1
}

手动实现一个最小堆(数组模拟)

理解堆本质的关键是掌握「完全二叉树的数组表示」和「上浮(sift-up)/下沉(sift-down)」操作:

立即学习C++免费学习笔记(深入)”;

  • 对于下标为 i 的节点,左子节点下标 = 2*i + 1,右子节点 = 2*i + 2,父节点 = (i-1)/2
  • 插入时:加到末尾,然后向上调整(与父节点比较并交换,直到满足堆序)
  • 弹出堆顶时:把最后一个元素移到堆顶,再向下调整(与较小的子节点交换,直到满足堆序)

简易最小堆实现(不带泛型,便于理解):

EasySub – AI字幕生成翻译工具
EasySub – AI字幕生成翻译工具

EasySub 是一款在线 AI 字幕生成器。 它提供AI语音识别、AI字幕生成、AI字幕翻译,本来就很简单的视频剪辑。

下载
#include 
#include 
using namespace std;

class MinHeap {
    vector heap;
    
    void siftDown(int i) {
        int n = heap.size();
        while (true) {
            int smallest = i;
            int left = 2*i + 1, right = 2*i + 2;
            if (left < n && heap[left] < heap[smallest]) smallest = left;
            if (right < n && heap[right] < heap[smallest]) smallest = right;
            if (smallest == i) break;
            swap(heap[i], heap[smallest]);
            i = smallest;
        }
    }
    
    void siftUp(int i) {
        while (i > 0) {
            int parent = (i-1)/2;
            if (heap[i] >= heap[parent]) break;
            swap(heap[i], heap[parent]);
            i = parent;
        }
    }

public:
    void push(int x) {
        heap.push_back(x);
        siftUp(heap.size()-1);
    }
    
    int top() {
        return heap.empty() ? -1 : heap[0];
    }
    
    void pop() {
        if (heap.empty()) return;
        heap[0] = heap.back();
        heap.pop_back();
        if (!heap.empty()) siftDown(0);
    }
    
    bool empty() { return heap.empty(); }
};

用 STL 堆算法手写堆操作(更底层)

C++ 提供了原始堆操作函数,可直接在 vector 或数组上构建/维护堆:

  • make_heap(first, last):将区间转为最大堆
  • push_heap(first, last):把末尾元素加入已建好的堆(调用前需先 push_back)
  • pop_heap(first, last):把堆顶移到末尾,剩余部分仍是堆(调用后需再 pop_back)
  • 若要最小堆,传入 greater() 作为比较器

示例:

#include 
#include 
#include 
using namespace std;

int main() {
    vector v = {3, 1, 4, 1, 5};
    make_heap(v.begin(), v.end()); // 构建最大堆
    cout << v[0] << endl; // 5

    v.push_back(2);
    push_heap(v.begin(), v.end()); // 插入 2 并调整
    cout << v[0] << endl; // 5 还是最大值

    pop_heap(v.begin(), v.end()); // 5 移到末尾
    v.pop_back(); // 真正删除
    cout << v[0] << endl; // 新的最大值
}

常见误区和注意事项

初学堆容易踩坑,这些点值得留意:

  • priority_queue 不支持随机访问或遍历,不能像 vector 那样用下标取中间元素
  • 修改堆中某个元素后,不会自动重排——必须重新建堆或手动调整(STL 没提供 update 接口)
  • 自定义类型需重载 运算符,或显式传入比较函数对象(如 greater>
  • 堆不是排序算法,但可以借助多次 pop 实现堆排序(O(n log n))

不复杂但容易忽略。

相关专题

更多
java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

1465

2023.10.24

Go语言中的运算符有哪些
Go语言中的运算符有哪些

Go语言中的运算符有:1、加法运算符;2、减法运算符;3、乘法运算符;4、除法运算符;5、取余运算符;6、比较运算符;7、位运算符;8、按位与运算符;9、按位或运算符;10、按位异或运算符等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

228

2024.02.23

php三元运算符用法
php三元运算符用法

本专题整合了php三元运算符相关教程,阅读专题下面的文章了解更多详细内容。

85

2025.10.17

string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

318

2023.08.02

int占多少字节
int占多少字节

int占4个字节,意味着一个int变量可以存储范围在-2,147,483,648到2,147,483,647之间的整数值,在某些情况下也可能是2个字节或8个字节,int是一种常用的数据类型,用于表示整数,需要根据具体情况选择合适的数据类型,以确保程序的正确性和性能。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

538

2024.08.29

c++怎么把double转成int
c++怎么把double转成int

本专题整合了 c++ double相关教程,阅读专题下面的文章了解更多详细内容。

52

2025.08.29

C++中int的含义
C++中int的含义

本专题整合了C++中int相关内容,阅读专题下面的文章了解更多详细内容。

197

2025.08.29

treenode的用法
treenode的用法

​在计算机编程领域,TreeNode是一种常见的数据结构,通常用于构建树形结构。在不同的编程语言中,TreeNode可能有不同的实现方式和用法,通常用于表示树的节点信息。更多关于treenode相关问题详情请看本专题下面的文章。php中文网欢迎大家前来学习。

535

2023.12.01

高德地图升级方法汇总
高德地图升级方法汇总

本专题整合了高德地图升级相关教程,阅读专题下面的文章了解更多详细内容。

43

2026.01.16

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Go 教程
Go 教程

共32课时 | 3.8万人学习

Go语言实战之 GraphQL
Go语言实战之 GraphQL

共10课时 | 0.8万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号