服务端视角的C++从入门到精通(二)

113 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第11天,点击查看活动详情

2 各种map的使用方法

C++里面的键值对,可以使用map这一类数据结构进行表达。之所以称为一类,是因为map里面也有好多类型。比如底层基于红黑树(Red Black Tree)的map,底层基于哈希表的unordered_map

键值对的含义就是,根据一个值A,可以快速查找到他对应的另一个值B,其中值A就叫做key,值B就叫做value。在mapunordered_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取到的顺序不确定。