目录
vector:
- 1.1 默认排序函数(升序)
- 1.2 自定义排序
map:
- 2.1 默认排序(升序)
- 2.2 根据
key
来自定义排序 - 2.3 根据
value
来自定义排序
set:
- 3.1 默认排序(升序)
- 3.2 自定义排序
priority_queue:
- 4.1 默认排序(大顶堆)
- 4.2 自定义排序
C++的STL确实好用,但是有时候需要用到排序,除了默认的排序以外,我们如何自定义排序呢?这篇就比较全面的总结了STL里面的排序问题。
1. vector
1.1 默认排序函数(升序)
vector
里面有sort
,使用<algorithm>
库文件即可,使用方法如下:
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main()
{
vector<int> nums = {1, 8, 4, 2, 12};
sort(nums.begin(), nums.end());
for (int i : nums)
cout << i << " ";
// 1 2 4 8 12
return 0;
}
也可以对char
、string
、pair
默认升序排序,其他double
之类的默认类型也是可以的,不予重述。
char
:直接根据ASCII
来升序排序的vector<char> my_char = {'z', 'c', 's', 'e', 'x'}; sort(my_char.begin(), my_char.end()); for (char i : my_char) cout << i << " "; // c e s x z
string
:根据字典序排序的vector<string> my_string = {"boy", "bag", "banana", "apple", "app", "zoo"}; sort(my_string.begin(), my_string.end()); for (string i : my_string) cout << i << " "; // app apple bag banana boy zoo
pair
:会首先按照pair
中的第一个key
排序,然后key
相同,对value
排序vector<pair<int, int>> my_pair = {{1, 12}, {2, 3}, {1, 2}}; sort(my_pair.begin(), my_pair.end()); for (pair<int, int> i : my_pair) cout << i.first << " " << i.second << endl; // 1 2 // 1 12 // 2 3
1.2 自定义排序
有时候需要自定义类型的比较,或者按照自己的比较方式来排序,这时候就需要自定义排序了
// 自定义比较函数,这里是按照一个pair的value大小来排序
bool cmp(pair<string, int> a, pair<string, int> b)
{
return a.second < b.second;
}
int main()
{
vector<pair<string, int>> my_pair = {{"abs", 2}, {"tmp", 31}, {"ceil", 1}};
sort(my_pair.begin(), my_pair.end(), cmp);
for (pair<string, int> i : my_pair)
cout << i.first << " " << i.second << endl;
// ceil 1
// abs 2
// tmp 31
return 0;
}
2. map
2.1 默认排序(升序)
默认的map
其实是排序的map
,它底层的实现是一个红黑树
,所以当插入数据的时候会默认根据key
来排序。
map<int, int> my_map = {{3, 12}, {2, 3}, {1, 2}};
for (auto i : my_map)
cout << i.first << " " << i.second << endl;
// 1 2
// 2 3
// 3 12
类似的同上面的vector
的一样。
2.2 根据key
来自定义排序
这里要想自定义类型或者自定义比较方式来排序,分为两种,一种是根据key
来自定义类型或比较方式排序;另一种是根据value
来自定义类型或比较方式排序。两种不一样,所以需要分开介绍。这里先说根据key
来自定义排序
// 比较器,这不是比较函数了
struct cmp
{
bool operator()(string a, string b)
{
if (a.size() == b.size())
return a < b;
return a.size() < b.size();
}
};
int main()
{
map<string, int, cmp> my_map = {{"a", 100}, {"tmp", 31}, {"zoo", 4}, {"abs", 2}, {"ceil", 1}};
for (auto i : my_map)
cout << i.first << " " << i.second << endl;
// a 100
// abs 2
// tmp 31
// zoo 4
// ceil 1
return 0;
}
2.3 根据value
来自定义排序
根据value
来排序就比较麻烦了,一般有两个解决方案:
- 再建立一个
new_map
,把原来的my_map
的key
和value
换一下插入到new_map
里面,然后根据key
来排序。 - 再建一个
vector
,把原来的my_map
插入vector
里面,然后排序。
以上两种方案都可以在上面找到,这里不重复叙述了。
3. set
3.1 默认排序(升序)
set
默认是排序的,和map
一样,底层也是红黑树
,所以自带排序(升序)
set<string> my_set = {"boy", "bag", "banana", "apple", "app", "zoo"};
for (auto i : my_set)
cout << i << " ";
// app apple bag banana boy zoo
3.2 自定义排序
和map
的按key
排序一样,自己写一个比较器就可以了,不予重述。
4. priority_queue
4.1 默认排序(大顶堆)
priority_queue
的底层实现的数据结构是堆
,默认是大顶堆
,就是最大的始终在顶上。(虽然底层的数据结构是堆
,但是因为建立的是完全二叉树,所以其实容器是vector
)
priority_queue<int> my_pq;
vector<int> nums = {1, 8, 4, 2, 12};
for (int i : nums)
my_pq.push(i);
while (!my_pq.empty())
{
cout << my_pq.top() << " ";
my_pq.pop();
}
// 12 8 4 2 1
4.2 自定义排序
前面说了priority_queue
底层的容器是vector
,所以在建堆的时候要指定容器。
// 自定义比较器
struct cmp
{
bool operator()(string a, string b)
{
if (a.size() == b.size())
return a < b;
return a.size() < b.size();
}
};
int main()
{
// 指定容器是vector<string>,比较器是cmp
priority_queue<string, vector<string>, cmp> my_pq;
vector<string> nums = {"boy", "bag", "banana", "apple", "app", "zoo"};
for (string i : nums)
my_pq.push(i);
while (!my_pq.empty())
{
cout << my_pq.top() << " ";
my_pq.pop();
}
// banana apple zoo boy bag app
return 0;
}
总结
只有vector使用的是比较函数,其他的都是比较器。