热门标签 | HotTags
当前位置:  开发笔记 > 运维 > 正文

C++STLpriority_queue自定义排序实现方法详解

这篇文章主要介绍了C++STLpriority_queue自定义排序实现方法详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

前面讲解 priority_queue 容器适配器时,还遗留一个问题,即当 头文件提供的排序方式(std::less 和 std::greater)不再适用时,如何自定义一个满足需求的排序规则。

首先,无论 priority_queue 中存储的是基础数据类型(int、double 等),还是 string 类对象或者自定义的类对象,都可以使用函数对象的方式自定义排序规则。例如:

#include
#include
using namespace std;
//函数对象类
template 
class cmp
{
public:
  //重载 () 运算符
  bool operator()(T a, T b)
  {
    return a > b;
  }
};
int main()
{
  int a[] = { 4,2,3,5,6 };
  priority_queue,cmp > pq(a,a+5);
  while (!pq.empty())
  {
    cout <

运行结果为:
2 3 4 5 6

注意,C++ 中的 struct 和 class 非常类似,前者也可以包含成员变量和成员函数,因此上面程序中,函数对象类 cmp 也可以使用 struct 关键字创建:

struct cmp
{
  //重载 () 运算符
  bool operator()(T a, T b)
  {
    return a > b;
  }
};

可以看到,通过在 cmp 类(结构体)重载的 () 运算符中自定义排序规则,并将其实例化后作为 priority_queue 模板的第 3 个参数传入,即可实现为 priority_queue 容器适配器自定义比较函数。

除此之外,当 priority_queue 容器适配器中存储的数据类型为结构体或者类对象(包括 string 类对象)时,还可以通过重载其 > 或者 <运算符,间接实现自定义排序规则的目的。

注意,此方式仅适用于 priority_queue 容器中存储的为类对象或者结构体变量,也就是说,当存储类型为类的指针对象或者结构体指针变量时,此方式将不再适用,而只能使用函数对象的方式。

要想彻底理解这种方式的实现原理,首先要搞清楚 std::less 和 std::greater 各自的底层实现。实际上, 头文件中的 std::less 和 std::greater ,各自底层实现采用的都是函数对象的方式。比如,std::less 的底层实现代码为:

template 
struct less {
  //定义新的排序规则
  bool operator()(const T &_lhs, const T &_rhs) const {
    return _lhs <_rhs;
  }
};

std::greater 的底层实现代码为:

template 
struct greater {
  bool operator()(const T &_lhs, const T &_rhs) const {
    return _lhs > _rhs;
  }
};

可以看到,std::less 和 std::greater 底层实现的唯一不同在于,前者使用 <号实现从大到小排序,后者使用 > 号实现从小到大排序。

那么,是否可以通过重载 <或者 > 运算符修改 std::less 和 std::greater 的排序规则,从而间接实现自定义排序呢?答案是肯定的,举个例子:

#include
#include
using namespace std;
class node {
public:
  node(int x = 0, int y = 0) :x(x), y(y) {}
  int x, y;
};
//新的排序规则为:先按照 x 值排序,如果 x 相等,则按 y 的值排序
bool operator <(const node &a, const node &b) {
  if (a.x > b.x) return 1;
  else if (a.x == b.x)
    if (a.y >= b.y) return 1;
  return 0;
}
int main() {
  //创建一个 priority_queue 容器适配器,其使用默认的 vector 基础容器以及 less 排序规则。
  priority_queue pq;
  pq.push(node(1, 2));
  pq.push(node(2, 2));
  pq.push(node(3, 4));
  pq.push(node(3, 3));
  pq.push(node(2, 3));
  cout <<"x y" <

输出结果为:
x y
1 2
2 2
2 3
3 3
3 4

可以看到,通过重载 <运算符,使得 std::less 变得适用了。
读者还可以自行尝试,通过重载 > 运算符,赋予 std::greater 和之前不同的排序方式。

当然,也可以以友元函数或者成员函数的方式重载 > 或者 <运算符。需要注意的是,以成员函数的方式重载 > 或者 <运算符时,该成员函数必须声明为 const 类型,且参数也必须为 const 类型,至于参数的传值方式是采用按引用传递还是按值传递,都可以(建议采用按引用传递,效率更高)。

例如,将上面程序改为以成员函数的方式重载 <运算符:

class node {
public:
  node(int x = 0, int y = 0) :x(x), y(y) {}
  int x, y;
  bool operator <(const node &b) const{
    if ((*this).x > b.x) return 1;
    else if ((*this).x == b.x)
      if ((*this).y >= b.y) return 1;
    return 0;
  }
};

同样,在以友元函数的方式重载 <或者 > 运算符时,要求参数必须使用 const 修饰。例如,将上面程序改为以友元函数的方式重载 <运算符。例如:

class node {
public:
  node(int x = 0, int y = 0) :x(x), y(y) {}
  int x, y;
  friend bool operator <(const node &a, const node &b);
};
//新的排序规则为:先按照 x 值排序,如果 x 相等,则按 y 的值排序
bool operator <(const node &a, const node &b){
  if (a.x > b.x) return 1;
  else if (a.x == b.x)
    if (a.y >= b.y) return 1;
  return 0;
}

总的来说,以函数对象的方式自定义 priority_queue 的排序规则,适用于任何情况;而以重载 > 或者 <运算符间接实现 priority_queue 自定义排序的方式,仅适用于 priority_queue 中存储的是结构体变量或者类对象(包括 string 类对象)。

到此这篇关于C++ STL priority_queue自定义排序实现方法详解的文章就介绍到这了,更多相关STL priority_queue自定义排序内容请搜索以前的文章或继续浏览下面的相关文章希望大家以后多多支持!


推荐阅读
  • Monkey《大话移动——Android与iOS应用测试指南》的预购信息发布啦!
    Monkey《大话移动——Android与iOS应用测试指南》的预购信息已经发布,可以在京东和当当网进行预购。感谢几位大牛给出的书评,并呼吁大家的支持。明天京东的链接也将发布。 ... [详细]
  • 基于layUI的图片上传前预览功能的2种实现方式
    本文介绍了基于layUI的图片上传前预览功能的两种实现方式:一种是使用blob+FileReader,另一种是使用layUI自带的参数。通过选择文件后点击文件名,在页面中间弹窗内预览图片。其中,layUI自带的参数实现了图片预览功能。该功能依赖于layUI的上传模块,并使用了blob和FileReader来读取本地文件并获取图像的base64编码。点击文件名时会执行See()函数。摘要长度为169字。 ... [详细]
  • IhaveconfiguredanactionforaremotenotificationwhenitarrivestomyiOsapp.Iwanttwodiff ... [详细]
  • 开发笔记:加密&json&StringIO模块&BytesIO模块
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了加密&json&StringIO模块&BytesIO模块相关的知识,希望对你有一定的参考价值。一、加密加密 ... [详细]
  • HDU 2372 El Dorado(DP)的最长上升子序列长度求解方法
    本文介绍了解决HDU 2372 El Dorado问题的一种动态规划方法,通过循环k的方式求解最长上升子序列的长度。具体实现过程包括初始化dp数组、读取数列、计算最长上升子序列长度等步骤。 ... [详细]
  • 本文讨论了Alink回归预测的不完善问题,指出目前主要针对Python做案例,对其他语言支持不足。同时介绍了pom.xml文件的基本结构和使用方法,以及Maven的相关知识。最后,对Alink回归预测的未来发展提出了期待。 ... [详细]
  • 本文介绍了如何找到并终止在8080端口上运行的进程的方法,通过使用终端命令lsof -i :8080可以获取在该端口上运行的所有进程的输出,并使用kill命令终止指定进程的运行。 ... [详细]
  • 本文讨论了如何优化解决hdu 1003 java题目的动态规划方法,通过分析加法规则和最大和的性质,提出了一种优化的思路。具体方法是,当从1加到n为负时,即sum(1,n)sum(n,s),可以继续加法计算。同时,还考虑了两种特殊情况:都是负数的情况和有0的情况。最后,通过使用Scanner类来获取输入数据。 ... [详细]
  • 本文介绍了九度OnlineJudge中的1002题目“Grading”的解决方法。该题目要求设计一个公平的评分过程,将每个考题分配给3个独立的专家,如果他们的评分不一致,则需要请一位裁判做出最终决定。文章详细描述了评分规则,并给出了解决该问题的程序。 ... [详细]
  • 本文介绍了C++中省略号类型和参数个数不确定函数参数的使用方法,并提供了一个范例。通过宏定义的方式,可以方便地处理不定参数的情况。文章中给出了具体的代码实现,并对代码进行了解释和说明。这对于需要处理不定参数的情况的程序员来说,是一个很有用的参考资料。 ... [详细]
  • 本文介绍了OC学习笔记中的@property和@synthesize,包括属性的定义和合成的使用方法。通过示例代码详细讲解了@property和@synthesize的作用和用法。 ... [详细]
  • 本文主要解析了Open judge C16H问题中涉及到的Magical Balls的快速幂和逆元算法,并给出了问题的解析和解决方法。详细介绍了问题的背景和规则,并给出了相应的算法解析和实现步骤。通过本文的解析,读者可以更好地理解和解决Open judge C16H问题中的Magical Balls部分。 ... [详细]
  • Mac OS 升级到11.2.2 Eclipse打不开了,报错Failed to create the Java Virtual Machine
    本文介绍了在Mac OS升级到11.2.2版本后,使用Eclipse打开时出现报错Failed to create the Java Virtual Machine的问题,并提供了解决方法。 ... [详细]
  • 本文讨论了使用差分约束系统求解House Man跳跃问题的思路与方法。给定一组不同高度,要求从最低点跳跃到最高点,每次跳跃的距离不超过D,并且不能改变给定的顺序。通过建立差分约束系统,将问题转化为图的建立和查询距离的问题。文章详细介绍了建立约束条件的方法,并使用SPFA算法判环并输出结果。同时还讨论了建边方向和跳跃顺序的关系。 ... [详细]
  • 本文介绍了MyBioSource转甲状腺素蛋白定量检测ELISA试剂盒的应用方法及特点。ELISA法作为一项新技术在免疫诊断中的应用范围不断扩大,不仅适用于多种病原微生物引起的传染病、非传染病的免疫诊断,也可用于大/小分子抗原的定量检测。ELISA法具有灵敏、特异、简单、快速、稳定及易于自动化操作等特点,是一种早期诊断的良好方法,也可用于血清流行病学调查。MyBioSource转甲状腺素蛋白定量检测ELISA试剂盒使用方法包括对血清和血浆的操作要求。 ... [详细]
author-avatar
傻要傻到嗨样
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有