携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第11天,点击查看活动详情
2 各种map的使用方法
C++里面的键值对,可以使用map这一类数据结构进行表达。之所以称为一类,是因为map里面也有好多类型。比如底层基于红黑树(Red Black Tree)的map,底层基于哈希表的unordered_map。
键值对的含义就是,根据一个值A,可以快速查找到他对应的另一个值B,其中值A就叫做key,值B就叫做value。在map和unordered_map中,key可以是任何可以哈希的数据类型,包括但不限于int这种基本数据类型,也包括string这种STL里的类,至于哪种数据类型是可以哈希的,这个在后面讲原理的时候会讲到。
具体的使用方法如下:
#include <map>
#include <iostream>
using namespace std;
int main() {
map<int, int> m1; // <>里面对应key、value的类型,前面是key、后面是value
m1[5]; // 就算这样写,如果没有这个key,还是会默认创建对应value的默认值
cout << m1[5] << endl;
m1[5] = 1; // 同一个key,则会替换相应的value
cout << m1[5] << endl;
cout << m1[6] << endl;
pair<int, int> p;
p.first = 4;
p.second = 2;
m1.insert(p);
cout << m1[4] << endl;
m1.insert({7, 9}); // 使用了初始化列表的方式传入pair
cout << m1[7] << endl;
cout << "m1 has:"
for(pair<int,int> i:m1){ // 使用C++11中的方法遍历map,其中pair<int,int>可以使用auto代替,进行自动类型推导
cout << "[" << i.first << ", " << i.second << "]";
}
cout << endl;
m1.erase(5); // 删掉key为5的键值对
for(auto i:m1) {
cout << "[" << i.first << ", " << i.second << "]";
}
cout << endl;
cout << m1.at(4) << endl; // at()函数和[]运算符的作用类似,不同的是at在不存在对应key时会在运行时报错
for(map<int,int>::iterator i=m1.begin();i!=m1.end();i++) { // 使用迭代器进行遍历
}
}
可以看到,遍历一个map其实可以有好多种方法的。 输出如下:
0
1
0
2
9
m1 has:[4, 2][5, 1][6, 0][7, 9]
[4, 2][6, 0][7, 9]
2
unordered_map的使用方法和map类似,区别在于,unordered_map由于底层数据结构是哈希表,所以读取的平均复杂度是O(1),而map底层是树形结构,所以平均时间复杂度是O(logN)。但是这也并不意味着unordered_map就一定比map要好,因为哈希是需要处理哈希冲突的、如果哈希函数设置不好那么查询效率也会迅速下降的,然后key也是无序的,这也就想要直接顺序地取key是不可能的了,然后也不支持范围查询、只能实现等值查询(这里在MySQL索引中也有类似的比较,后面的文章里会讲到)等。当然,unordered_map也是可以遍历的,遍历方法和对map遍历一样,只不过key取到的顺序不确定。