C++ 进阶基础之九

大纲

set 与 multiset 容器

set 与 multiset 容器的概念

set 容器的概念

set 是一个集合容器,其中所包含的元素是唯一的,集合中的元素会自动按一定的顺序排列。元素插入过程是按排序规则插入,所以不能指定插入位置。set 的元素不像 map 那样可以同时拥有实值和键值,set 的元素即是键值又是实值。Set 不允许两个元素有相同的键,也不可以通过 set 的迭代器改变 set 元素的值,因为 set 元素值就是其键值,关系到 set 元素的排序规则。如果任意改变 set 元素值,会严重破坏 set 的组织。换句话说 set 的 iterator 是一种 const iterator。set 拥有和 list 某些相同的性质,当对容器中的元素进行插入操作或者删除操作的时候,操作之前所有的迭代器,在操作完成之后依然有效,被删除的那个元素的迭代器必然是一个例外。

multiset 容器的概念

multiset 的特性及用法和 set 完全相同,唯一的区别在于它允许元素重复。set 和 multiset 的底层实现都是红黑树,而红黑树是平衡二叉树的一种。二又树就是任何节点最多允许有两个字节点,分别是左子结点和右子节点,如下图所示:

总结

  • set 采用红黑树变体的数据结构实现,红黑树属于平衡二叉树,在插入操作和删除操作上比 vector 快。
  • set 不可以直接存取元素,即不可以使用 at.(pos) 函数和 [] 操作符。
  • multiset 与 set 的区别:set 支持唯一键值,每个元素值只能出现一次;而 multiset 中同一值可以出现多次。
  • 不可以直接修改 set 或 multiset 容器中的元素值,因为这类容器是自动排序的,如果希望修改一个元素值,必须先删除原有的元素,再插入新的元素。

set 与 multiset 容器的使用

set 与 multiset 的构造与赋值

默认构造函数
1
2
3
4
5
6
7
set<int> setInt;         // 一个存放 int 数据的 set 容器
set<float> setFloat; // 一个存放 float 数据的 set 容器
set<string> setString; // 一个存放 string 数据的 set 容器

multiset<int> mulsetInt; // 一个存放 int 数据的 multiset 容器
multi set<float> multisetFloat; // 一个存放 float 数据的 multiset 容器
multi set<string> multisetString; // 一个存放 string 数据的 multiset 容器
赋值操作说明
1
2
3
4
5
6
7
set(const set &st);              // 拷贝构造函数
set& operator=(const set &st); // 重载等号操作符
set.swap(st); // 交换两个集合容器

multiset(const multiset &mst); // 拷贝构造函数
multiset& operator=(const multiset &mst); // 重载等号操作符
multiset.swap(mst); // 交换两个集合容器
构造与赋值的使用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
#include <iostream>
#include <set>

using namespace std;

void printSet(set<int> &s) {
// 遍历容器
for (set<int>::iterator it = s.begin(); it != s.end(); it++) {
cout << *it << " ";
}
cout << endl;
}

void printMultiSet(multiset<int> &s) {
// 遍历容器
for (set<int>::iterator it = s.begin(); it != s.end(); it++) {
cout << *it << " ";
}
cout << endl;
}

int main() {

cout << "------ set 构造函数 ------" << endl;

// 默认构造函数
set<int> s1;

// 关联式容器,默认按照 Key 从小到大排序
s1.insert(5);
s1.insert(2);
s1.insert(9);
s1.insert(4);
s1.insert(3);
printSet(s1);

// 拷贝构造函数
set<int> s2 = s1;
printSet(s2);

cout << "------ set 赋值操作 ------" << endl;

// 赋值操作,重载等号操作符
set<int> s3;
s3 = s1;
printSet(s3);

// 赋值操作,将其他容器与本身的元素互换
set<int> s4;
s4.insert(10);
s4.insert(30);
s4.insert(20);
s4.swap(s1);
printSet(s1);
printSet(s4);

cout << "------ multiset 构造函数 ------" << endl;

multiset<int> s5;

// multiset 允许插入多个相同的元素
s5.insert(5);
s5.insert(2);
s5.insert(2);
s5.insert(3);
s5.insert(3);
printMultiSet(s5);

// 拷贝构造函数
multiset<int> s6 = s5;
printMultiSet(s6);

cout << "------ multiset 赋值操作 ------" << endl;

// 赋值操作,重载等号操作符
multiset<int> s7;
s7 = s5;
printMultiSet(s7);

// 赋值操作,将其他容器与本身的元素互换
multiset<int> s8;
s8.insert(10);
s8.insert(30);
s8.insert(20);
s8.swap(s5);
printMultiSet(s5);
printMultiSet(s8);

return 0;
}

程序运行输出的结果如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
------ set 构造函数 ------
2 3 4 5 9
2 3 4 5 9
------ set 赋值操作 ------
2 3 4 5 9
10 20 30
2 3 4 5 9
------ multiset 构造函数 ------
2 2 3 3 5
2 2 3 3 5
------ multiset 赋值操作 ------
2 2 3 3 5
10 20 30
2 2 3 3 5

set 与 multiset 的迭代器

1
2
3
4
5
6
7
8
9
set.begin();            // 返回容器中第一个数据的迭代器
set.end(); // 返回容器中最后一个数据之后的迭代器
set.rbegin(); // 返回容器中倒数第一个元素的迭代器
set.rend(); // 返回容器中倒数最后一个元素的后面的迭代器

multiset.begin(); // 返回容器中第一个数据的迭代器
multiset.end(); // 返回容器中最后一个数据之后的迭代器
multiset.rbegin(); // 返回容器中倒数第一个元素的迭代器
multiset.rend(); // 返回容器中倒数最后一个元素的后面的迭代器

set 与 multiset 的常用操作

提示

multiset 的特性及用法和 set 完全相同,唯一的区别在于它允许元素重复。因此在下述的例子中只介绍 set 的常用操作,而 multiset 的常用操作不再累述。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
#include <iostream>
#include <set>

using namespace std;

void printSet(set<int> &s) {
// 遍历容器
for (set<int>::iterator it = s.begin(); it != s.end(); it++) {
cout << *it << " ";
}
cout << endl;
}

int main() {
cout << "------ set 插入操作 ------" << endl;
set<int> s1;
s1.insert(3);
s1.insert(9);
s1.insert(5);
s1.insert(8);
printSet(s1);

cout << "------ set 大小操作 ------" << endl;

// 获取容器大小
cout << "size = " << s1.size() << endl;

// 判断容器是否为空
cout << "isEmpty = " << (s1.empty() ? "true" : "false") << endl;

cout << "------ set 查找操作 ------" << endl;

// 查找键 Key 的元素个数,返回结果是 0 或者 1
int count = s1.count(8);
cout << "count = " << count << endl;

// 查找键 Key 是否存在,若存在,则返回该键的元素的迭代器,若不存在,则返回 set.end() 迭代器
set<int>::iterator pos = s1.find(8);
if (pos != s1.end()) {
cout << "found value for " << *pos << endl;
} else {
cout << "not found value" << endl;
}

// 返回第一个 key >= keyElem 元素的迭代器,若不存在,则返回 set.end() 迭代器
set<int>::iterator pos2 = s1.lower_bound(8);
if (pos2 != s1.end()) {
cout << "found lower_bound(8) result is " << *pos2 << endl;
}
else {
cout << "note found lower_bound(8) result" << endl;
}

// 返回第一个 key > keyElem 元素的迭代器,若不存在,则返回 set.end() 迭代器
set<int>::iterator pos3 = s1.upper_bound(8);
if (pos3 != s1.end()) {
cout << "found upper_bound(8) result is " << *pos3 << endl;
}
else {
cout << "note found upper_bound(8) result" << endl;
}

// 返回容器中 key 与 keyElem 相等的上下限的两个迭代器(即上限是 lower_bound,下限是 upper_bound),若不存在,则返回 set.end() 迭代器
pair<set<int>::iterator, set<int>::iterator> result = s1.equal_range(8);
// 获取第一个结果值
if (result.first != s1.end()) {
cout << "found equal_range(8) first result is " << *result.first << endl;
}
else {
cout << "note found equal_range(8) first result" << endl;
}
// 获取第二个结果值
if (result.second != s1.end()) {
cout << "found equal_range(8) second result is " << *result.second << endl;
}
else {
cout << "note found equal_range(8) second result" << endl;
}

cout << "------ set 删除操作 ------" << endl;

// 删除迭代器所指的元素,返回下一个元素的迭代器
s1.erase(s1.begin());
printSet(s1);

// 删除容器中值为 elem 的元素
s1.erase(5);
printSet(s1);

cout << "------ set 清空操作 ------" << endl;

s1.clear();
printSet(s1);

return 0;
}

程序运行输出的结果如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
------ set 插入操作 ------
3 5 8 9
------ set 大小操作 ------
size = 4
isEmpty = false
------ set 查找操作 ------
count = 1
found value for 8
found lower_bound(8) result is 8
found upper_bound(8) result is 9
found equal_range(8) first result is 8
found equal_range(8) second result is 9
------ set 删除操作 ------
5 8 9
8 9
------ set 清空操作 ------

set 不允许插入重复元素

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#include <iostream>
#include <set>

using namespace std;

void printSet(set<int> &s) {
// 遍历容器
for (set<int>::iterator it = s.begin(); it != s.end(); it++) {
cout << *it << " ";
}
cout << endl;
}

int main() {
set<int> s1;

pair<set<int>::iterator, bool> result = s1.insert(10);
// 判断是否插入成功
if (result.second) {
cout << "insert success" << endl;
} else {
cout << "insert failed" << endl;
}

result = s1.insert(10);
// 判断是否插入成功
if (result.second) {
cout << "insert success" << endl;
} else {
cout << "insert failed" << endl;
}

printSet(s1);

return 0;
}

程序运行输出的结果如下:

1
2
3
insert success
insert failed
10

set 对元素进行排序操作

set 容器默认会对基础数据类型的元素进行升序排序(从小到大),若需要更改 set 容器的排序规则,需要在 set 容器初始化的时候指定排序规则。值得一提的是,如果需要自定义 set 容器的排序规则,那么就需要使用到 C++ 的仿函数(Functor),也被称作函数对象或者伪函数。

1
2
set<int, less<int>> setIntA;      // 容器按升序方式排列元素(从小到大)
set<int, greater<int>> setIntB; // 容器按降序方式排列元素(从大到小)

提示

  • set<int> 相当于 set<int, less<int>>,两者都是按升序方式排列元素(从小到大)。
  • less<int>greater<int> 中的 int 可以改成其它类型,该类型主要要跟 set 容纳的数据类型一致。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
#include <iostream>
#include <set>

using namespace std;

// 仿函数
class myCustomCompare {
public:
// 重载
bool operator()(const int &v1, const int &v2) {
// 排序规则
return v1 > v2;
}
};

void printSet(set<int> &s) {
// 遍历容器
for (set<int>::iterator it = s.begin(); it != s.end(); it++) {
cout << *it << " ";
}
cout << endl;
}

void printGreaterSet(set<int, greater<int>> &s) {
// 遍历容器
for (set<int>::iterator it = s.begin(); it != s.end(); it++) {
cout << *it << " ";
}
cout << endl;
}

void printCustomCompareSet(set<int, myCustomCompare> &s) {
// 遍历容器
for (set<int>::iterator it = s.begin(); it != s.end(); it++) {
cout << *it << " ";
}
cout << endl;
}

int main() {
// 容器按升序方式排列元素(从小到大)
set<int, less<int>> s2;
s2.insert(5);
s2.insert(1);
s2.insert(7);
s2.insert(3);
s2.insert(9);
printSet(s2);

// 容器按降序方式排列元素(从大到小)
set<int, greater<int>> s3;
s3.insert(5);
s3.insert(1);
s3.insert(7);
s3.insert(3);
s3.insert(9);
printGreaterSet(s3);

// 按照自定义的排序方式排列元素
set<int, myCustomCompare> s4;
s4.insert(5);
s4.insert(1);
s4.insert(7);
s4.insert(3);
s4.insert(9);
s4.insert(9);
printCustomCompareSet(s4);

return 0;
}

程序运行输出的结果如下:

1
2
3
1 3 5 7 9 
9 7 5 3 1
9 7 5 3 1

set 插入自定义数据类型

特别注意

由于 set 容器中的元素默认会按一定的顺序排列,所以往 set 容器插入自定义数据类型时,必须在 set 容器初始化的时候指定仿函数(即自定义的排序规则),否则无法向 set 容器中插入自定义数据类型。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
#include <iostream>
#include <set>
#include <string>

using namespace std;

// 自定义数据类型
class Person {

public:
Person(string name, int age) {
this->name = name;
this->age = age;
}

string getName() const {
return this->name;
}

int getAge() const {
return this->age;
}

private:
string name;
int age;

};

// 仿函数
class myCompare {
public:
// 重载
bool operator()(const Person &p1, const Person &p2) {
// 排序规则
return p1.getAge() > p2.getAge();
}
};

void printCustomSet(set<Person, myCompare> &p) {
// 遍历容器
for (set<Person, myCompare>::iterator it = p.begin(); it != p.end(); it++) {
cout << "name: " << it->getName() << ", age: " << it->getAge() << endl;
}
}

int main() {
// 使用仿函数,让 set 容器按照年龄进行倒序排序(从大到小)
set<Person, myCompare> s1;

Person p1("Tom", 18);
Person p2("Peter", 20);
Person p3("Jim", 15);
Person p4("David", 28);

s1.insert(p1);
s1.insert(p2);
s1.insert(p3);
s1.insert(p4);

printCustomSet(s1);

return 0;
}

程序运行输出的结果如下:

1
2
3
4
name: David, age: 28
name: Peter, age: 20
name: Tom, age: 18
name: Jim, age: 15

map 和 multimap 容器

map 和 multimap 容器的概念

map 是 STL 的一个关联式容器,它提供一对一(其中第一个称为关键字,每个关键字只能在 map 中出现一次,第二个称为该关键字的值)的数据处理能力。map 容器存储的都是 pair 对象,也就是用 pair 类模板创建的键值对。其中,各个键值对的键和值可以是任意数据类型,包括 C++ 基本数据类型(intdouble 等)、使用结构体或类自定义的类型。通常情况下,map 容器中存储的各个键值对都选用 string 字符串作为键的类型。map 内部自建了一颗红黑树 (一种非严格意义上的平衡二叉树),这颗树具有对数据自动排序的功能,所以在 map 内部所有的数据都是有序的。map 的特点是增加和删除节点对迭代器的影响很小,除了那个被操作的节点,对其他的节点都没有什么影响。使用 map 容器存储的各个键值对,键的值既不能重复也不能被修改。map 可以根据 key 值快速查找记录,复杂度在 log(n) 级别,如果有 1000 条记录,最多查找 10 次,如果有 1000000 条记录,最多查找 20 次。**multimap 与 map 的区别:map 支持唯一键值,每个键只能出现一次;而在 multimap 中相同键可以出现多次。

总结

  • map 是标准的关联式容器,一个 map 是一个键值对序列,即 (key - value) 对。它提供基于 key 的快速检索能力。
  • map 中 key 值是唯一的。集合中的元素按一定的顺序排列。元素插入过程是按排序规则插入,所以不能指定插入到指定位置。
  • map 的底层实现采用红黑树变体的平衡二叉树的数据结构,在插入操作和删除操作上比 vector 快。
  • map 可以直接存取 key 所对应的 value,支持 [] 操作符,如 map[key] = value
  • multimap 与 map 的区别:map 支持唯一键值,每个键只能出现一次;而在 multimap 中相同键可以出现多次。
  • map 支持 [] 操作符,而 multimap 不支持 [] 操作符。

map 和 multimap 容器的使用

map 和 multimap 的构造与赋值

默认构造函数

map 与 multimap 采用模板类实现,map 对象的默认构造形式:map<T1, T2> mapTT;,其中 <> 尖括号内还可以设置指针类型或自定义类型

1
2
map<int, char> mapA;
map<string, float> mapB;
1
2
multimap<int, char> multimapA;
multimap<string, float> multimapB;
赋值操作说明
1
2
3
map(const map &mp);              // 拷贝构造函数
map& operator=(const map &mp); // 重载等号操作符
map.swap(mp); // 交换两个集合容器的元素
1
2
3
multimap(const map &mp);              // 拷贝构造函数
multimap& operator=(const map &mp); // 重载等号操作符
multimap.swap(mp); // 交换两个集合容器的元素

map 和 multimap 的常用操作

multimap 的特性及用法和 map 完全相同,唯一的区别在于它允许相同的键可以出现多次。因此在下述的例子中只介绍 map 的常用操作,而 multimap 的常用操作不再累述。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
#include <iostream>
#include <map>

using namespace std;

int main() {

cout << "------ map 插入操作 ------" << endl;

// 默认构造函数
map<int, int> m;

// 第一种数据插入方式
m.insert(pair<int, int>(1, 2));
// 第二种数据插入方式(推荐)
m.insert(make_pair(3, 4));
// 第三种数据插入方式
m.insert(map<int, int>::value_type(5, 6));
// 第四种数据插入方式
m[7] = 8;

cout << "------ map 遍历操作 ------" << endl;

// 第一种方式遍历 map 集合
for (map<int, int>::iterator it = m.begin(); it != m.end(); it++) {
cout << "key: " << it->first << " , value: " << it->second << endl;
}

// 第二种方式遍历 map 集合
for (auto it = m.begin(); it != m.end(); it++) {
cout << "key = " << it->first << " , value = " << it->second << endl;
}

cout << "------ map 存取操作 ------" << endl;

// 获取指定的 key
map<int, int>::iterator item = m.find(5);
cout << "key = " << item->first << " , value = " << item->second << endl;

// 第一种方式判断 key 是否存在
// 如果 key 存在,find() 函数会返回 key 对应的迭代器,如果 key 不存在,find() 函数会返回尾后迭代器 end()
if (m.find(100) == m.end()) {
cout << "key " << 100 << " not exist" << endl;
}

// 第二种方式判断 key 是否存在
// count() 函数用于统计 key 值在 map 中出现的次数,map 的 key 是不允许重复的,因此如果 key 存在会返回 1,不存在会返回 0
if (m.count(5) == 1) {
cout << "key " << 5 << " existed" << endl;
}

// 返回第一个 key >= keyElem 元素的迭代器
map<int, int>::iterator result1 = m.lower_bound(3);
if (result1 != m.end()) {
cout << "found result for lower_bound(3), key: " << result1->first << ", value: " << result1->second << endl;
} else {
cout << "not found result for lower_bound(3)";
}

// 返回第一个 key > keyElem 元素的迭代器
map<int, int>::iterator result2 = m.upper_bound(3);
if (result2 != m.end()) {
cout << "found result for upper_bound(3), key: " << result2->first << ", value: " << result2->second << endl;
} else {
cout << "not found result for upper_bound(3)";
}

// 返回容器中 key 与 keyElem 相等的上下限的两个容器
pair<map<int, int>::iterator, map<int, int>::iterator> result3 = m.equal_range(3);
// 上限的容器
if (result3.first != m.end()) {
cout << "found lower_bound for equal_range(3), key: " << result3.first->first << ", value: " << result3.first->second << endl;
} else {
cout << "not found lower_bound for equal_range(3)" << endl;
}
// 下限的容器
if (result3.second != m.end()) {
cout << "found upper_bound for equal_range(3), key: " << result3.second->first << ", value: " << result3.second->second << endl;
} else {
cout << "not found upper_bound for equal_range(3)";
}

cout << "------ map 删除操作 ------" << endl;

// 删除指定的 key
m.erase(7);
for (auto it = m.begin(); it != m.end(); it++) {
cout << "key = " << it->first << " , value = " << it->second << endl;
}

}

程序运行输出的结果如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
------ map 插入操作 ------
------ map 遍历操作 ------
key: 1 , value: 2
key: 3 , value: 4
key: 5 , value: 6
key: 7 , value: 8
key = 1 , value = 2
key = 3 , value = 4
key = 5 , value = 6
key = 7 , value = 8
------ map 存取操作 ------
key = 5 , value = 6
key 100 not exist
key 5 existed
found result for lower_bound(3), key: 3, value: 4
found result for upper_bound(3), key: 5, value: 6
found lower_bound for equal_range(3), key: 3, value: 4
found upper_bound for equal_range(3), key: 5, value: 6
------ map 删除操作 ------
key = 1 , value = 2
key = 3 , value = 4
key = 5 , value = 6

map 对元素进行排序操作

map 容器默认会对基础数据类型的 key 进行升序排序(从小到大),若需要更改 map 容器的排序规则,需要在 map 容器初始化的时候指定排序规则。值得一提的是,如果需要自定义 map 容器的排序规则,那么就需要使用到 C++ 的仿函数(Functor),也被称作函数对象或者伪函数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#include <iostream>
#include <map>

using namespace std;

// 仿函数
class myCompare {

public:
// 重载
bool operator()(const int &v1, const int &v2) {
// 排序规则
return v1 > v2;
}
};

void printMap(map<int, int, myCompare> &m) {
// 遍历容器
for (map<int, int, myCompare>::iterator it = m.begin(); it != m.end(); it++) {
cout << "key = " << it->first << ", value = " << it->second << endl;
}
}

int main() {
// 使用仿函数,让 map 容器按照 key 进行倒序排序(从大到小)
map<int, int, myCompare> m1;
m1.insert(make_pair(1, 8));
m1.insert(make_pair(7, 2));
m1.insert(make_pair(4, 10));
m1.insert(make_pair(9, 5));
printMap(m1);
return 0;
}

程序运行输出的结果如下:

1
2
3
4
key = 9, value = 5
key = 7, value = 2
key = 4, value = 10
key = 1, value = 8

map 使用自定义数据类型作为 Key

特别注意

由于 map 容器中的元素默认会根据 key 按一定的顺序排列,所以往 map 容器插入 key 为自定义数据类型的元素时,必须在 map 容器初始化的时候指定仿函数(即自定义的排序规则),否则无法向 map 容器中插入 key 为自定义数据类型的元素。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
#include <iostream>
#include <map>

using namespace std;

// 自定义数据类型
class Person {

public:
Person(string name, int age) {
this->name = name;
this->age = age;
}

string getName() const {
return this->name;
}

int getAge() const {
return this->age;
}

private:
string name;
int age;

};

// 仿函数
class myCompare {
public:
// 重载
bool operator()(const Person &p1, const Person &p2) {
// 排序规则
return p1.getAge() > p2.getAge();
}
};

void printMap(map<Person, string, myCompare> &m) {
// 遍历容器
for (map<Person, string, myCompare>::iterator it = m.begin(); it != m.end(); it++) {
cout << "age = " << it->first.getAge() << ", name = " << it->first.getName() << ", role = " << it->second << endl;
}
}

int main() {
// 使用仿函数,让 map 容器按照年龄进行倒序排序(从大到小)
map<Person, string, myCompare> m1;
m1.insert(make_pair(Person("Tom", 19), "Student"));
m1.insert(make_pair(Person("Jim", 18), "Student"));
m1.insert(make_pair(Person("Peter", 28), "Teacher"));
printMap(m1);
return 0;
}

程序运行输出的结果如下:

1
2
3
age = 28, name = Peter, role = Teacher
age = 19, name = Tom, role = Student
age = 18, name = Jim, role = Student