C++ STL 自定义排序总结
C++ 仿函数和自定义排序函数的总结
前置知识(重中之重)
- 在STL中我们一般有两种自定义排序的方式,一种是对sort的排序规则进行自定义,一种是对STL容器自己的排序规则进行自定义,这两种方式的区别在于:
- 对sort函数进行自定义的时候既可以使用仿函数(必须是谓词)也可以使用普通函数
- 对STL容器自己的排序规则进行自定义的时候,只能使用仿函数,因为C++的模板编程需要传入模板类型而不是函数指针,所以自定义的普通函数在这里是无效的。
- 使用仿函数的时候,函数声明后面函数体前面必须加上const,将该函数设置为常量成员函数,表示该函数的隐含this指针被设置为了const指针,即无法在该函数内修改成员变量的值。(只读模式)有关于这一部分可以参照 这里
具体到每一个STL容器的细节
一、map和set
1. 一些基本认识
- 通常不使用对关联容器使用泛型算法。对于许多需要通过迭代器去修改key的值的泛型算法,关联容器的迭代器不支持这种操作,所以无法使用;而对于一些仅用于访问元素的算法,出于效率考虑,也不推荐使用泛型算法。
- map和set的单个元素的底层其实都是pair,只不过set的value始终为空,由此可以看出map和set的性质其实基本是一致的。
- map和set都只能使用key进行排序,如果尝试进行根据value的排序会报错。
- 由于map和set的底层实现是红黑树,插入的过程中已经做好了排序,所以map和set后期均无法使用sort进行排序。(即,只能在模板中指定其排序的仿函数)
2. 使用仿函数对map排序的具体写法
- 对一个
map<int, int, MyMapSort>
的key进行降序排序(a>b说明a比b大的时候排在b的前面)
class MyMapSort {
public:
bool operator() (int a, int b) const {
return a > b;
}
};
- 如何根据value来对map进行排序?(使用vector替代map来存储pair,然后使用sort进行排序)
typedef pair<int, int> Pair;
vector<Pair> v;
class MyVectorSort {
public:
bool operator() (const Pair& a, const Pair& b) const {
return a.second > b.second;
}
};
sort(v.begin(), v.end(), MyVectorSort());
-
由于vector是可以根据里面装的元素来进行排序的,所以operator()的形参为Pair类型。
-
从以上写法可以看出来,仿函数实际上是重载了类的operator(),让这个类在外部看来可以跟函数一样使用。STL的模板中也只能将接收这种参数作为自定义排序的手段。
二、vector
1. 一些基本认识
- vector底层是用数组实现的
- 支持sort排序
2. 自定义vector的排序的写法
-
在模板中使用仿函数进行自定义排序:不支持这种操作,底层是数组,也没有办法高效的实现每次插入都排序。
-
在sort中使用仿函数或者自定义函数进行排序上面已经写过仿函数的,这里来写自定义函数的
typedef pair<int, int> Pair;
vector<Pair> v;
bool myCompare (const Pair& a, const Pair& b) {
return a.second > b.second;
}
sort(v.begin(), v.end(), myCompare); // 注意这里不需要加括号了,因为传递的是函数指针