文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

如何在C++中使用STL关联式容器自定义排序规则

2023-06-06 18:15

关注

如何在C++中使用STL关联式容器自定义排序规则?相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。

1) 使用函数对象自定义排序规则

#include <iostream>#include <set>  // set#include <string>  // stringusing namespace std;//定义函数对象类class cmp {public: //重载 () 运算符 bool operator ()(const string &a,const string &b) {  //按照字符串的长度,做升序排序(即存储的字符串从短到长)  return (a.length() < b.length()); }};int main() { //创建 set 容器,并使用自定义的 cmp 排序规则 std::set<string, cmp>myset{"http://jb51.net.net/stl/",        "http://jb51.net.net/python/",        "http://jb51.net.net/java/"}; //输出容器中存储的元素 for (auto iter = myset.begin(); iter != myset.end(); ++iter) {   cout << *iter << endl; } return 0;}

程序执行结果为:
http://jb51.net.net/stl/
http://jb51.net.net/java/
http://jb51.net.net/python/

重点分析一下 6~13 行代码,其定义了一个函数对象类,并在其重载 () 运算符的方法中自定义了新的排序规则,即按照字符串的长度做升序排序。在此基础上,程序第 17 行代码中,通过将函数对象类的类名 cmp 通过 set 类模板的第 2 个参数传递给 myset 容器,该容器内部排序数据的规则,就改为了以字符串的长度为标准做升序排序。
需要注意的是,此程序中创建的 myset 容器,由于是以字符串的长度为准进行排序,因此其无法存储相同长度的多个字符串。

另外,C++ 中的 struct 和 class 非常类似(有关两者区别,可阅读《C++ struct和class到底有什么区别》一文),前者也可以包含成员变量和成员函数。因此上面程序中,函数对象类 cmp 也可以使用 struct 关键字创建:

//定义函数对象类struct cmp { //重载 () 运算符 bool operator ()(const string &a, const string &b) {  //按照字符串的长度,做升序排序(即存储的字符串从短到长)  return (a.length() < b.length()); }};

值得一提的是,在定义函数对象类时,也可以将其定义为模板类。比如:

//定义函数对象模板类template <typename T>class cmp {public: //重载 () 运算符 bool operator ()(const T &a, const T &b) {  //按照值的大小,做升序排序  return a < b; }};

注意,此方式必须保证 T 类型元素可以直接使用关系运算符(比如这里的 < 运算符)做比较。

2) 重载关系运算符实现自定义排序

其实在 STL 标准库中,本就包含几个可供关联式容器使用的排序规则,如表 1 表示。

表 1 C++ STL标准库适用于关联式容器的排序规则

排序规则功能
std::less<T>   底层采用 < 运算符实现升序排序,各关联式容器默认采用的排序规则。
std::greater<T>底层采用 > 运算符实现降序排序,同样适用于各个关联式容器。
std::less_equal<T>底层采用 <= 运算符实现升序排序,多用于 multimap 和 multiset 容器。
std::greater_equal<T>底层采用 >= 运算符实现降序排序,多用于 multimap 和 multiset 容器。

值得一提的是,表 1 中的这些排序规则,其底层也是采用函数对象的方式实现的。以 std::less<T> 为例,其底层实现为:

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

在此基础上,当关联式容器中存储的数据类型为自定义的结构体变量或者类对象时,通过对现有排序规则中所用的关系运算符进行重载,也能实现自定义排序规则的目的。

注意,当关联式容器中存储的元素类型为结构体指针变量或者类的指针对象时,只能使用函数对象的方式自定义排序规则,此方法不再适用。

举个例子:

#include <iostream>#include <set>  // set#include <string>  // stringusing namespace std;//自定义类class myString {public: //定义构造函数,向 myset 容器中添加元素时会用到 myString(string tempStr) :str(tempStr) {}; //获取 str 私有对象,由于会被私有对象调用,因此该成员方法也必须为 const 类型 string getStr() const;private: string str;};string myString::getStr() const{ return this->str;}//重载 < 运算符,参数必须都为 const 类型bool operator <(const myString &stra, const myString & strb) { //以字符串的长度为标准比较大小 return stra.getStr().length() < strb.getStr().length();}int main() { //创建空 set 容器,仍使用默认的 less<T> 排序规则 std::set<myString>myset; //向 set 容器添加元素,这里会调用 myString 类的构造函数 myset.emplace("http://jb51.net.net/stl/"); myset.emplace("http://jb51.net.net/c/"); myset.emplace("http://jb51.net.net/python/"); // for (auto iter = myset.begin(); iter != myset.end(); ++iter) {  myString mystr = *iter;  cout << mystr.getStr() << endl; } return 0;}

程序执行结果为:
http://jb51.net.net/c/
http://jb51.net.net/stl/
http://jb51.net.net/python/

在这个程序中,虽然 myset 容器表面仍采用默认的 std::less<T> 排序规则,但由于我们对其所用的 < 运算符进行了重载,使得 myset 容器内部实则是以字符串的长度为基准,对各个 mystring 类对象进行排序。

另外,上面程序以全局函数的形式实现对 < 运算符的重载,还可以使用成员函数或者友元函数的形式实现。其中,当以成员函数的方式重载 < 运算符时,该成员函数必须声明为 const 类型,且参数也必须为 const 类型:

bool operator <(const myString & tempStr) const { //以字符串的长度为标准比较大小 return this->str.length() < tempStr.str.length();}

至于参数的传值方式是采用按引用传递还是按值传递,都可以(建议采用按引用传递,效率更高)。

同样,如果以友元函数的方式重载 < 运算符时,要求参数必须使用 const 修饰:

//类中友元函数的定义friend bool operator <(const myString &a, const myString &b);//类外部友元函数的具体实现bool operator <(const myString &stra, const myString &strb) { //以字符串的长度为标准比较大小 return stra.str.length() < strb.str.length();}

看完上述内容,你们掌握如何在C++中使用STL关联式容器自定义排序规则的方法了吗?如果还想学到更多技能或想了解更多相关内容,欢迎关注编程网行业资讯频道,感谢各位的阅读!

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     807人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     351人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     314人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     433人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     221人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯