c++中priority_queue怎么自定义排序

来源:IPIPP.com作者:美谷头衔:网络博主
导读:本期聚焦于小伙伴创作的《c++中priority_queue怎么自定义排序》,敬请观看详情,探索知识的价值。以下视频、文章将为您系统阐述其核心内容与价值。如果您觉得《c++中priority_queue怎么自定义排序》有用,将其分享出去将是对创作者最好的鼓励。

在c++的标准模板库中,priority_queue是一种优先队列容器适配器,它的底层默认基于大顶堆实现,默认排序规则是元素值从大到小排列,队首元素是当前队列中的最大值。但实际开发中我们往往需要自定义排序规则,比如让队列按照元素从小到大出队,或者按照自定义结构体的某个成员排序,下面介绍几种常见的自定义排序实现方式。

c++中priority_queue怎么自定义排序

使用内置的greater和less模板

priority_queue的模板参数有三个,分别是元素类型、底层容器类型、比较规则类型,默认的比较规则是less,也就是大顶堆。如果我们想要实现小顶堆,也就是元素从小到大出队,可以直接把第三个模板参数指定为greater。

需要注意的是,使用greater需要包含<functional>头文件,同时底层容器要支持随机访问,默认使用的vector是满足要求的。

#include <iostream>
#include <queue>
#include <functional>
#include <vector>

int main() {
    // 定义小顶堆优先队列,元素从小到大出队
    std::priority_queue<int, std::vector<int>, std::greater<int>> minHeap;
    minHeap.push(3);
    minHeap.push(1);
    minHeap.push(2);
    // 输出队列元素,顺序为1 2 3
    while (!minHeap.empty()) {
        std::cout << minHeap.top() << " ";
        minHeap.pop();
    }
    std::cout << std::endl;
    return 0;
}

自定义仿函数实现排序

当我们需要按照自定义的规则排序时,比如按照结构体的某个成员排序,或者按照复杂的逻辑判断,可以自定义仿函数作为priority_queue的比较规则。仿函数本质是重载了operator()运算符的结构体或类,priority_queue会用这个仿函数的返回值来判断元素的优先级。

仿函数的返回值需要是bool类型,当返回true时,表示第一个参数的优先级低于第二个参数,在默认的堆调整逻辑中,优先级高的元素会放在队首。

#include <iostream>
#include <queue>
#include <vector>
#include <string>

// 自定义学生结构体
struct Student {
    std::string name;
    int score;
};

// 自定义仿函数,按照分数从高到低排序
struct CompareStudent {
    bool operator()(const Student& a, const Student& b) {
        // 返回true表示a的优先级低于b,也就是分数低的优先级低
        return a.score < b.score;
    }
};

int main() {
    // 使用自定义仿函数作为比较规则
    std::priority_queue<Student, std::vector<Student>, CompareStudent> stuHeap;
    stuHeap.push({"张三", 85});
    stuHeap.push({"李四", 92});
    stuHeap.push({"王五", 78});
    // 输出顺序为李四 张三 王五
    while (!stuHeap.empty()) {
        Student topStu = stuHeap.top();
        std::cout << topStu.name << " " << topStu.score << std::endl;
        stuHeap.pop();
    }
    return 0;
}

重写结构体的operator<运算符

如果我们不想额外定义仿函数,也可以直接在自定义结构体中重写operator<运算符,priority_queue默认使用less比较规则,而less会调用元素的operator<来判断优先级,所以我们重写operator<就可以改变默认的排序逻辑。

这里要注意operator<的逻辑要和我们需要的排序规则对应,比如我们想要分数高的优先级高,那么当a的分数大于b的分数时,a的优先级应该更高,对应的operator<应该返回a.score < b.score吗?不对,这里需要理清楚:less的比较逻辑是,如果a < b为true,那么b的优先级比a高。所以如果我们想要分数高的优先级高,那么当a的分数比b高时,a的优先级更高,也就是a < b应该为false,所以operator<的逻辑应该是return a.score < b.score,和仿函数的逻辑是一致的。

#include <iostream>
#include <queue>
#include <vector>
#include <string>

struct Student {
    std::string name;
    int score;
    // 重写operator<,按照分数从高到低排序
    bool operator<(const Student& other) const {
        // 分数高的优先级高,所以当当前对象分数小于other分数时,当前对象优先级低
        return score < other.score;
    }
};

int main() {
    // 不需要额外指定比较规则,使用默认的less即可
    std::priority_queue<Student> stuHeap;
    stuHeap.push({"张三", 85});
    stuHeap.push({"李四", 92});
    stuHeap.push({"王五", 78});
    // 输出顺序为李四 张三 王五
    while (!stuHeap.empty()) {
        Student topStu = stuHeap.top();
        std::cout << topStu.name << " " << topStu.score << std::endl;
        stuHeap.pop();
    }
    return 0;
}

使用lambda表达式作为比较规则

c++11之后支持lambda表达式,我们也可以把lambda表达式作为priority_queue的比较规则,不过需要注意的是,lambda表达式的类型是匿名的,所以我们需要用decltype来获取它的类型,并且在构造priority_queue的时候传入lambda表达式的实例。

#include <iostream>
#include <queue>
#include <vector>
#include <string>

struct Student {
    std::string name;
    int score;
};

int main() {
    // 定义lambda表达式,按照分数从低到高排序
    auto cmp = [](const Student& a, const Student& b) {
        return a.score > b.score;
    };
    // 使用decltype获取lambda类型,构造时传入lambda实例
    std::priority_queue<Student, std::vector<Student>, decltype(cmp)> stuHeap(cmp);
    stuHeap.push({"张三", 85});
    stuHeap.push({"李四", 92});
    stuHeap.push({"王五", 78});
    // 输出顺序为王五 张三 李四
    while (!stuHeap.empty()) {
        Student topStu = stuHeap.top();
        std::cout << topStu.name << " " << topStu.score << std::endl;
        stuHeap.pop();
    }
    return 0;
}

注意事项

  • priority_queue的第三个模板参数是比较类型,不是比较实例,所以如果使用仿函数或者lambda,需要保证类型正确,lambda场景还需要传入实例。
  • 自定义比较规则的时候要注意逻辑的正确性,避免优先级判断反了导致排序不符合预期。
  • 底层容器默认是vector,也可以指定为deque,但是必须支持随机访问迭代器,不能用list。

priority_queue自定义排序greaterless仿函数修改时间:2026-06-12 06:21:18

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。