1. 映射
- 最大的优点就是找东西快,检索效率高,因为内部的平衡有序二叉树(红黑树)。
- 从红黑树的任何一个节点往下看,左右子树的层级可以差一层但不能超过一层。
- 找1的话,从根节点往下看,1小于3,找左子树,1又小于2,找左子树,找到1。只找了两次,这就不是线性级的效率,而是对数级别的效率,一砍砍一半。
- 映射容器中的节点们的物理模型是红黑树,每个节点都是pair对象,pair对象有first和second构成。
- 迭代器it中的当前指向,指向的是容器的节点,*it是节点的引用, 而映射容器中的每个节点都是pair对象,所以可以理解为映射的迭代器相当于指向 pair对象的指针。
- 映射中的键不能改(要是改了红黑树就不是红黑树了)。而且每当添加一个节点,可能就会有好多节点的顺序需要发生变化,构建和修改性能差。
- 上图中的insert不是重载,而是不同的写法
- 1 利用pair类的构造函数来构造一个pair对象
- 2 make_pair函数来构造pair对象
- find不是全局那个,而是映射容器的成员函数,利用红黑树去找, 贼快。
#include <iostream>
#include <map>
using namespace std;
class Candidate{
public:
Candidate(string name = ""):m_name(name), m_vote(0){}
string m_name;
int m_vote;
};
void print(map<char, Candidate>& m){
typedef map<char, Candidate>::iterator IT;
for(IT it = m.begin(); it != m.end(); ++it){
cout << "(" << (*it).first<< ")" << (*it).second.m_name << ' ';
}
cout << endl;
}
int main() {
map<char, Candidate> m;
// 3种添加映射容器节点的方式, 每加一个节点,映射容器内部会按键值重新排序
// 1. 用pair的构造函数
m.insert(pair<char , Candidate>('B', Candidate("关羽")));
// 2. 用make_pair函数
m.insert(make_pair('A', Candidate("张飞")));
// 3. 用下标,返回新节点值的引用
m['C'] = Candidate("赵云");
typedef map<char, Candidate>::iterator IT;
// 让5个人进行投票
for(int i = 0; i < 5; i++){
print(m);
char ch;
cin >> ch;
// find, 成功返回找到的迭代器, 失败返回终止迭代
IT fit = m.find(ch);
if(fit == m.end()){
cout << "废票" << endl;
continue;
}
++(*fit).second.m_vote;
}
for(IT it=m.begin(); it != m.end(); ++it){
cout << (*it).second.m_name << ":" << (*it).second.m_vote << endl;
}
return 0;
}
$ ./a.out
(A)张飞 (B)关羽 (C)赵云
A
(A)张飞 (B)关羽 (C)赵云
1
废票
(A)张飞 (B)关羽 (C)赵云
A
(A)张飞 (B)关羽 (C)赵云
C
(A)张飞 (B)关羽 (C)赵云
B
张飞:2
关羽:1
赵云:1
2. 多重映射
表示一对多的逻辑关系, 允许键重复的映射,所以不支持下标运算,容器内部也是红黑树的逻辑结构,每个节点也是pair对象。
#include <iostream>
#include <map>
using namespace std;
int main() {
multimap<string, int> m;
m.insert(make_pair("张飞", 100));
m.insert(make_pair("刘备", 100));
m.insert(make_pair("薛辉", 100));
m.insert(make_pair("张飞", 80));
m.insert(make_pair("刘备", 70));
m.insert(make_pair("薛辉", 60));
typedef multimap<string, int>::iterator IT;
for(IT it = m.begin(); it != m.end(); ++it){
cout << (*it).first << ": " << (*it).second << endl;
}
return 0;
}
$ ./a.out
刘备: 100
刘备: 70
张飞: 100
张飞: 80
薛辉: 100
薛辉: 60
3. 集合
内部结构依然是红黑树,比在向量等基本容器找东西快,毕竟对数级别搜索,这里的节点就不是键值对pair,只有value
#include <iostream>
#include <set>
using namespace std;
int main() {
set<int> s;
s.insert(1);
s.insert(2);
s.insert(2);
s.insert(3);
s.insert(3);
cout << "size: " << s.size()<< endl;
typedef set<int>::iterator IT;
for(IT it = s.begin(); it != s.end(); ++it){
cout << *it << " ";
}
cout << endl;
return 0;
}
$ ./a.out
size: 3
1 2 3
4. 多重集合
内部逻辑还是红黑树结构
#include <iostream>
#include <set>
using namespace std;
int main() {
multiset<int> s;
s.insert(1);
s.insert(2);
s.insert(2);
s.insert(3);
s.insert(3);
cout << "size: " << s.size()<< endl;
typedef multiset<int>::iterator IT;
for(IT it = s.begin(); it != s.end(); ++it){
cout << *it << " ";
}
cout << endl;
return 0;
}
$ ./a.out
size: 5
1 2 2 3 3