c++ 集合排序
std::sort vector string
我们先看一下 std::sort 的定义。头文件
template< class RandomIt >
void sort( RandomIt first, RandomIt last ); (1)
template< class RandomIt, class Compare >
void sort( RandomIt first, RandomIt last, Compare comp ); (2)
Sorts the elements in the range [first, last) in non-descending order. The order of equal elements is not guaranteed to be preserved. 【即不稳定排序】
(1)式:Elements are compared using operator<.【默认使用operator<运算符比较】
(2)式:Elements are compared using the given binary comparison function comp.【使用comp比较元素大小】
关于 comp 参数:
The signature of the comparison function should be equivalent to the following:
bool cmp(const Type1 &a, const Type2 &b);
若第一参数小于(即先序于)第二参数则返回 true。cmp函数为bool类型,那么如果返回true,相当于不交换位置
复杂度:
平均 O(N·log(N)) 次比较,其中 N = std::distance(first, last)
例子:
#include <vector>
#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
bool cmp(const int& a, const int& b) {
return a > b;
}
int main()
{
vector<int> arr = { 3,4,5,2,4,5,6 };
// 1.
// sort(arr.begin(), arr.end());
// 2.
//sort(arr.begin(), arr.end(), cmp);
// 3. 使用 cpp 定义好的函数 #include <functional>
//sort(arr.begin(), arr.end(), greater<int>());
// 4. 使用自定义的类
struct compare
{
bool operator()(int a, int b) const
{
return a > b;
}
};
compare my_cmp;
sort(arr.begin(), arr.end(), my_cmp);
for (auto& item : arr)
cout << item << ' ';
return 0;
}
map 排序
template < class Key, // map::key_type
class T, // map::mapped_type
class Compare = less<Key>, // map::key_compare
class Alloc = allocator<pair<const Key,T> > // map::allocator_type
> class map;
可以看到 map 同 sort 一样,可以传入一个 Compare 类,缺省是 less
template<class _Ty = void>
struct less
{ // functor for operator<
constexpr bool operator()(const _Ty& _Left, const _Ty& _Right) const
{ // apply operator< to operands
return (_Left < _Right);
}
};
less 类是个模板类。里面是重载了 operator(),内部的比较是 operator< 实现的。所以如果我们想改变 map 的自动 key 排序方式,就可以传入自定义的比较类。
key 自定义排序
#include <map>
#include <string>
#include <iostream>
using namespace std;
struct Compare // key 的排序 降序
{
bool operator()(const string& s1, const string& s2) const
{
return s1 > s2;
}
};
int main()
{
map<string, int, Compare> my_set;
my_set.insert(make_pair(string("2dx"), 3));
my_set[string("6dx")] = 7;
my_set["3dx"] = 7;
for (auto& item : my_set)
{
cout << item.first << ' ' << item.second << endl;
}
return 0;
}
6dx 7
3dx 7
2dx 3
按照value排序
我们知道 sort 函数只能对顺序容器如 vector, string 排序使用。所以,我们可以换个思路,将 map 先转入到 vecotr 中,再自定义按照 value 排序
#include <map>
#include <vector>
#include <string>
#include <algorithm>
#include <iostream>
using namespace std;
typedef pair<string, int> PAIR;
struct
{
bool operator()(const PAIR& p1, const PAIR& p2)
{
// 按照 value 降序
if (p2.second > p1.second)
return true;
else if (p2.second > p1.second)
return false;
else
{
// 按照 key 升序
if (p1.first < p1.first)
return true;
else
return false;
}
}
}Compare;
int main()
{
map<string, int> my_map = {
{"3th", 4}, {"2th", 7}, {"1th", 7}
};
vector<PAIR> my_vector;
copy(my_map.begin(), my_map.end(), back_inserter(my_vector));
sort(my_vector.begin(), my_vector.end(), Compare);
for (auto& item : my_vector)
{
cout << item.first << ' ' << item.second << endl;
}
return 0;
}
3th 4
1th 7
2th 7
set 排序
set方式1 重载元素本身<运算符
但是对于 set map 等本身有序的函数,即在插入的时候,会通过比较元素选择插入的位置,所以我们可以通过重载 operator < 运算符实现自定义排序
#include <set>
#include <string>
#include <iostream>
using namespace std;
struct stu
{
string name;
int age;
bool operator< (const stu& p) const // const必须写.
{
if (age < p.age) // 按照 age 降序
return false;
else if (age > p.age)
return true;
else
{
return name < p.name; // 否则, 按照 name 升序
}
}
};
int main()
{
set<stu> my_set;
stu s;
my_set.insert(stu{ string("2dx"), 3 });
my_set.insert(stu{ string("2dx"), 7 });
my_set.insert(stu{ string("3dx"), 7 });
for (auto& item : my_set)
{
cout << item.name << ' ' << item.age << endl;
}
return 0;
}
2dx 7
2dx 7
2dx 3
set 方式2 传入比较类
如果我们看 set 定义的方法
template<
class Key,
class Compare = std::less<Key>,
class Allocator = std::allocator<Key>
> class set;
可以看到其实 set 会有内置的比较方法,所以,除了对类方法进行重载,我们还可以传入一个比较函数。也就类似于 sort function 中的 cmp
#include <set>
#include <string>
#include <iostream>
using namespace std;
struct stu
{
string name;
int age;
};
struct Compare
{
bool operator()(const stu& p1, const stu& p2)
{
if (p1.age < p2.age) // 按照 age 降序
return false;
else if (p1.age > p2.age)
return true;
else
{
return p1.name < p2.name; // 否则, 按照 name 升序
}
}
};
int main()
{
set<stu, Compare> my_set;
stu s;
my_set.insert(stu{ string("2dx"), 3 });
my_set.insert(stu{ string("2dx"), 7 });
my_set.insert(stu{ string("3dx"), 7 });
for (auto& item : my_set)
{
cout << item.name << ' ' << item.age << endl;
}
return 0;
}
2dx 7
3dx 7
2dx 3