• C++ STL之容器(使用方法)


    1. 容器简介

           容器就是数据结构,用来将数据元素按照一定的规则进行排列,不同的容器拥有不同的排列规则,不同的排列规则可以达到不同的数据操作特点。容器只需要提供迭代器 算法只需要拿到迭代器就可以完成容器和算法之间的关联和操作

    • 顺序容器:数组(array),动态数组(vector),双向队列(deque),双向链表(list),单向链表(forward_list),字符串(string)
    • 关联容器:map、set、multimap、multiset、unordered_set、unordered_map、unordered_multiset、unordered_multimap
    • 容器适配器:单向队列(queue),栈(stack)

    Alt
    Alt
    alt

    2. String

           string 封装了 char*,管理这个字符串,是一个 char*型的容器。string 管理 char*所分配的内存。每一次 string 的复制,取值都由 string 类负责维护,不用担心复制越界和取值越界等。

    2.1 构造操作

    string();//创建一个空的字符串 例如: string str;
    string(const string& str);//使用一个 string 对象初始化另一个 string 对象
    string(const char* s);//使用字符串 s 初始化
    string(int n, char c);//使用 n 个字符 c 初始化
    //例子:
    //默认构造函数
    string s1;
    //拷贝构造函数
    string s2(s1);
    string s2 = s1;
    //带参数构造函数
    char* str = "itcast";
    string s3(str);
    string s4(10, 'a');
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    2.2 赋值操作

    string& operator=(const char* s);//char*类型字符串 赋值给当前的字符串
    string& operator=(const string &s);//把字符串 s 赋给当前的字符串
    string& operator=(char c);//字符赋值给当前的字符串
    string& assign(const char *s);//把字符串 s 赋给当前的字符串
    string& assign(const char *s, int n);//把字符串 s 的前 n 个字符赋给当前的字符串
    string& assign(const string &s);//把字符串 s 赋给当前字符串
    string& assign(int n, char c);//用 n 个字符 c 赋给当前字符串
    string& assign(const string &s, int start, int n);//将 s 从 start 开始 n 个字符赋值给字符串
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    2.3 常用操作(存取字符串、拼接、 查找、替换、比较、插入、删除)

    //存取字符串
    char& operator[](int n);//通过[]方式取字符,越界程序挂掉
    char& at(int n);//通过 at 方法获取字符,越界会抛出异常
    
    string s = "itcast";
    char c = s[1];
    c = s.at(1);
    
    //拼接
    string& operator+=(const string& str);//重载+=操作符
    string& operator+=(const char* str);//重载+=操作符
    string& operator+=(const char c);//重载+=操作符
    string& append(const char *s);//把字符串 s 连接到当前字符串结尾
    string& append(const char *s, int n);//把字符串 s 的前 n 个字符连接到当前字符串结尾
    string& append(const string &s);//同 operator+=()
    string& append(const string &s, int pos, int n);//把字符串 s 中从 pos 开始的 n 个字符连接到当前字符串结尾
    string& append(int n, char c);//在当前字符串结尾添加 n 个字符 c
    
    //查找和替换
    int find(const string& str, int pos = 0) const; //查找 str 第一次出现位置,从 pos 开始查找
    int find(const char* s, int pos = 0) const; //查找 s 第一次出现位置,从 pos 开始查找
    int find(const char* s, int pos, int n) const; //从 pos 位置查找 s 的前 n 个字符第一次位置
    int find(const char c, int pos = 0) const; //查找字符 c 第一次出现位置
    int rfind(const string& str, int pos = npos) const;//查找 str 最后一次位置,从 pos 开始查找
    int rfind(const char* s, int pos = npos) const;//查找 s 最后一次出现位置,从 pos 开始查找
    int rfind(const char* s, int pos, int n) const;//从 pos 查找 s 的前 n 个字符最后一次位置
    int rfind(const char c, int pos = 0) const; //查找字符 c 最后一次出现位置
    string& replace(int pos, int n, const string& str); //替换从 pos 开始 n 个字符为字符串 str
    string& replace(int pos, int n, const char* s); //替换从 pos 开始的 n 个字符为字符串 s
    
    //比较
    int compare(const string &s) const;//与字符串 s 比较,等于时返回0
    int compare(const char *s) const;//与字符串 s 比较,等于时返回0
    
    //切割子串
    string substr(int pos = 0, int n = npos) const;//返回由 pos 开始的 n 个字符组成的字符串
    
    //插入删除
    string& insert(int pos, const char* s); //插入字符串
    string& insert(int pos, const string& str); //插入字符串
    string& insert(int pos, int n, char c);//在指定位置插入 n 个字符 c
    string& erase(int pos, int n = npos);//删除从 Pos 开始的 n 个字符
    
    • 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

    3. Vector

           vector 是个动态数组,连续内存空间,随机存取效率高。当空间不足的时候插入新元素,vector 会重新申请一块更大的内存空间(每次增长一倍),将旧空间数据拷贝到新空间,然后释放旧空间。vector 是单口容器,所以在尾端插入和删除元素效率较高,在指定位置插入,势必会引起数据元素移动,效率较低
    在这里插入图片描述

    3.1 构造操作

    vector<T> v; //采用模板实现类实现,默认构造函数
    vector(v.begin(), v.end());//将 v[begin(), end())区间中的元素拷贝给本身。
    vector(n, elem);//构造函数将 n 个 elem 拷贝给本身。
    vector(const vector &vec);//拷贝构造函数。
    //例子 使用第二个构造函数 我们可以...
    int arr[] = {2,3,4,1,9};
    vector<int> v1(arr, arr + sizeof(arr) / sizeof(int));
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    3.2 赋值操作

    assign(beg, end);//将[beg, end)区间中的数据拷贝赋值给本身。
    assign(n, elem);//将 n 个 elem 拷贝赋值给本身。
    vector& operator=(const vector &vec);//重载等号操作符
    swap(vec);// 将 vec 与本身的元素互换,实际交换彼此的指针
    //第一个赋值函数,可以这么写:
    int arr[] = { 0, 1, 2, 3, 4 };
    assign(arr, arr + 5);//使用数组初始化 vector
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    3.3 常用操作(大小、 查找、替换、比较、插入、删除)

    //大小
    size();//返回容器中元素的个数
    empty();//判断容器是否为空
    resize(int num);//重新指定容器的长度为 num,若容器变长,则以默认值填充新位置。如果容器变短,则末尾超出容器长度的元素被删除。
    resize(int num, elem);//重新指定容器的长度为 num,若容器变长,则以 elem 值填充新位置。如果容器变短,则末尾超出容器长>度的元素被删除。
    capacity();//容器的容量,因为当容空间器不够时会⾃动扩充空间 ,但不⼀定都会填满,所以可能与size()不等
    reserve(int len);//容器预留 len 个元素长度,预留位置不初始化,元素不可访问。
    //reserve 是容器预留空间,但在空间内不真正创建元素对象,所以在没有添加新的对象之前,不能引用容器内的元素
    //resize 是改变容器的大小,且在创建对象,因此,调用这个函数之后,就可以引用容器内的对象了.
    
    //存取
    at(int idx); //返回索引 idx 所指的数据,如果 idx 越界,抛出 out_of_range 异常。
    operator[];//返回索引 idx 所指的数据,越界时,运行直接报错
    front();//返回容器中第一个数据元素
    back();//返回容器中最后一个数据元素
    
    //插入和删除
    insert(const_iterator pos, int count,ele);//迭代器指向位置 pos 插入 count 个元素 ele.
    push_back(ele); //尾部插入元素 ele
    pop_back();//删除最后一个元素
    erase(const_iterator start, const_iterator end);//删除迭代器从 start 到 end 之间的元素
    erase(const_iterator pos);//删除迭代器指向的元素
    clear();//删除容器中所有元素
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    4. Deque

           deque 则是一种双向开口的连续性空间,所谓双向开口,意思是可以在头尾两端分别做元素的插入和删除操作,vector 当然也可以在头尾两端进行插入和删除操作,但是头部插入和删除操作效率奇差,无法被接受。deque是动态的以分段的连续空间组合而成,随时可以增加一段新的空间并链接起来,由中控器来维持连续的假象
    在这里插入图片描述
    在这里插入图片描述

    4.1 构造操作

    deque<T> deqT;//默认构造形式
    deque(beg, end);//构造函数将[beg, end)区间中的元素拷贝给本身。
    deque(n, elem);//构造函数将 n 个 elem 拷贝给本身。
    deque(const deque &deq);//拷贝构造函数。
    
    • 1
    • 2
    • 3
    • 4

    4.2 赋值操作

    assign(beg, end);//将[beg, end)区间中的数据拷贝赋值给本身。
    assign(n, elem);//将 n 个 elem 拷贝赋值给本身。
    deque& operator=(const deque &deq); //重载等号操作符
    swap(deq);// 将 deq 与本身的元素互换
    
    • 1
    • 2
    • 3
    • 4

    4.3 常用操作(大小、插入、删除、存取)

    //大小
    deque.size();//返回容器中元素的个数
    deque.empty();//判断容器是否为空
    deque.resize(num);//重新指定容器的长度为 num,若容器变长,则以默认值填充新位置。如果容器变短,则末尾超出容器长度的元素被删除。
    deque.resize(num, elem); //重新指定容器的长度为 num,若容器变长,则以 elem 值填充新位置,如果容器变短,则末尾超出容器长度的元素被删除。
    
    //插入和删除
    push_back(elem);//在容器尾部添加一个数据
    push_front(elem);//在容器头部插入一个数据
    pop_back();//删除容器最后一个数据
    pop_front();//删除容器第一个数据
    insert(pos,elem);//在 pos 位置插入一个 elem 元素的拷贝,返回新数据的位置。
    insert(pos,n,elem);//在 pos 位置插入 n 个 elem 数据,无返回值。
    insert(pos,beg,end);//在 pos 位置插入[beg,end)区间的数据,无返回值。
    at(idx);//返回索引 idx 所指的数据,如果 idx 越界,抛出 out_of_range。
    operator[];//返回索引 idx 所指的数据,如果 idx 越界,不抛出异常,直接出错。
    front();//返回第一个数据。
    back();//返回最后一个数据
    
    //存取
    at(idx);//返回索引 idx 所指的数据,如果 idx 越界,抛出 out_of_range。
    operator[];//返回索引 idx 所指的数据,如果 idx 越界,不抛出异常,直接出错。
    front();//返回第一个数据。
    back();//返回最后一个数据
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    5. Stack

           stack是一种先进后出(first in last out,FILO)的数据结构,它只有一个出口,stack 只允许在栈顶新增元素,移除元素,获得顶端元素,但是除了顶端之外,其他地方不允许存取元素,只有栈顶元素可以被外界使用,也就是说stack不具有遍历行为,没有迭代器
    在这里插入图片描述

    5.1 构造操作

    stack<T> stkT;//stack 采用模板类实现, stack 对象的默认构造形式:
    stack(const stack &stk);//拷贝构造函数
    
    • 1
    • 2

    5.2 赋值操作

    stack& operator=(const stack &stk);//重载等号操作符
    
    • 1

    5.3 存取操作

    push(elem);//向栈顶添加元素
    pop();//从栈顶移除第一个元素
    top();//返回栈顶元素
    
    • 1
    • 2
    • 3

    5.4 大小操作

    empty();//判断堆栈是否为空
    size();//返回堆栈的大小
    
    • 1
    • 2

    6. Queue

           queue 是一种先进先出(first in first out, FIFO)的数据类型,他有两个口,数据元素只能从一个口进,从另一个口出。队列只允许从队尾加入元素,队头删除元素,必须符合先进先出的原则,queue 和 stack 一样不具有遍历行为。
    在这里插入图片描述

    6.1 构造操作

    queue<T> queT;//queue 采用模板类实现,queue 对象的默认构造形式:
    queue(const queue &que);//拷贝构造函数
    
    • 1
    • 2

    6.2 赋值操作

    queue& operator=(const queue &que);//重载等号操作符
    
    • 1

    6.3 存取操作

    push(elem);//往队尾添加元素
    pop();//从队头移除第一个元素
    back();//返回最后一个元素
    front();//返回第一个元素
    
    • 1
    • 2
    • 3
    • 4

    6.4 大小操作

    empty();//判断队列是否为空
    size();//返回队列的大小
    
    • 1
    • 2

    7. List

           链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成。每个结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域。STL中的list为双向链表,索引时迭代器可前进或后退。

    • 采用动态存储分配,不会造成内存浪费和溢出
    • 链表执行插入和删除操作十分方便,修改指针即可,不需要移动大量元素
    • 链表灵活,但是空间和时间额外耗费较大
      在这里插入图片描述

    7.1 构造操作

    list<T> lstT;//list 采用采用模板类实现,对象的默认构造形式:
    list(beg,end);//构造函数将[beg, end)区间中的元素拷贝给本身。
    list(n,elem);//构造函数将 n 个 elem 拷贝给本身。
    list(const list &lst);//拷贝构造函数。
    
    • 1
    • 2
    • 3
    • 4

    7.2 赋值操作

    assign(beg, end);//将[beg, end)区间中的数据拷贝赋值给本身。
    assign(n, elem);//将 n 个 elem 拷贝赋值给本身。
    list& operator=(const list &lst);//重载等号操作符
    swap(lst);//将 lst 与本身的元素互换。
    
    • 1
    • 2
    • 3
    • 4

    7.3 存取操作

    front();//返回第一个元素。
    back();//返回最后一个元素。
    
    • 1
    • 2

    7.4 常用操作(插入、删除、大小、排序)

    //插入和删除
    push_back(elem);//在容器尾部加入一个元素
    pop_back();//删除容器中最后一个元素
    push_front(elem);//在容器开头插入一个元素
    pop_front();//从容器开头移除第一个元素
    insert(pos,elem);//在 pos 位置插 elem 元素的拷贝,返回新数据的位置。
    insert(pos,n,elem);//在 pos 位置插入 n 个 elem 数据,无返回值。
    insert(pos,beg,end);//在 pos 位置插入[beg,end)区间的数据,无返回值。
    clear();//移除容器的所有数据
    erase(beg,end);//删除[beg,end)区间的数据,返回下一个数据的位置。
    erase(pos);//删除 pos 位置的数据,返回下一个数据的位置。
    remove(elem);//删除容器中所有与 elem 值匹配的元素。
    
    //大小
    size();//返回容器中元素的个数
    empty();//判断容器是否为空
    resize(num);//重新指定容器的长度为 num,若容器变长,则以默认值填充新位置。
    
    //反转排列排序
    reverse();//反转链表,比如 lst 包含 1,3,5 元素,运行此方法后,lst 就包含 5,3,1 元素。
    sort(); //list 排序
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    8. Set/Multiset

           set/multiset 的特性是所有元素会根据元素的值自动进行排序(默认从小到大排序)。set 是以 RB-tree(红黑树,平衡二叉树的一种)为底层机制,其查找效率非常好。set 容器中不允许重复元素,multiset 允许重复元素。set 集合是根据元素值进行排序,关系到 set 的排序规则,如果任意改变 set 的元素值,会严重破坏 set 组织。
    在这里插入图片描述

    8.1 构造操作

    set<T> st;//set 默认构造函数:
    set<T,func> st;//当T为对象时,需要指定针对于该对象的排序规则,即传入仿函数func
    mulitset<T> mst; //multiset 默认构造函数:
    set(const set &st);//拷贝构造函数
    
    • 1
    • 2
    • 3
    • 4

    8.2 赋值操作

    set& operator=(const set &st);//重载等号操作符
    swap(st);//交换两个集合容器
    
    • 1
    • 2

    8.3 常用操作(大小、插入、删除、查找)

    //大小
    size();//返回容器中元素的数目
    empty();//判断容器是否为空
    
    //插入和删除
    insert(elem);//在容器中插入元素。
    clear();//清除所有元素
    erase(pos);//删除 pos 迭代器所指的元素,返回下一个元素的迭代器。
    erase(beg, end);//删除区间[beg,end)的所有元素 ,返回下一个元素的迭代器。
    erase(elem);//删除容器中值为 elem 的元素。
    
    //查找
    find(key);//查找键 key 是否存在,若存在,返回该键的元素的迭代器;若不存在,返回 map.end();
    lower_bound(keyElem);//返回第一个 key>=keyElem 元素的迭代器。
    upper_bound(keyElem);//返回第一个 key>keyElem 元素的迭代器。
    equal_range(keyElem);//返回容器中 key 与 keyElem 相等的上下限的两个迭代器。
    pair<set<int>::iterator,set<int>::iterator> ret = equal_range(2);
    ret.first//第一个迭代器
    ret.second//第二个迭代器
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    9. Map/Multimap

           map 相对于 set 区别,map 具有键值和实值,所有元素根据键值自动排序。pair 的第一元素被称为键值,第二元素被称为实值。map 也是以红黑树为底层实现机制。

    9.1 构造操作

    map<T1, T2> mapTT;//map 默认构造函数,key:value
    map(const map &mp);//拷贝构造函数
    
    • 1
    • 2

    9.2 赋值操作

    map& operator=(const map &mp);//重载等号操作符
    swap(mp);//交换两个集合容器
    
    • 1
    • 2

    9.3 常用操作(大小、插入、删除、查找)

    //大小
    size();//返回容器中元素的数目
    empty();//判断容器是否为空
    
    //插入和删除
    map.insert(...); //往容器插入元素,返回 pair
    map<int, string> mapStu;
    // 第一种 通过 pair 的方式插入对象
    mapStu.insert(pair<int, string>(3, "小张"));
    // 第二种 通过 pair 的方式插入对象
    mapStu.inset(make_pair(-1, "校长"));
    // 第三种 通过 value_type 的方式插入对象
    mapStu.insert(map<int, string>::value_type(1, "小李"));
    // 第四种 通过数组的方式插入值
    mapStu[3] = "小刘";
    mapStu[5] = "小王";
    clear();//删除所有元素
    erase(pos);//删除 pos 迭代器所指的元素,返回下一个元素的迭代器。
    erase(beg,end);//删除区间[beg,end)的所有元素 ,返回下一个元素的迭代器。
    erase(keyElem);//删除容器中 key 为 keyElem 的对组。
    
    //查找
    find(key);//查找键 key 是否存在,若存在,返回该键的元素的迭代器;/若不存在,返回 map.end();
    count(keyElem);//返回容器中 key 为 keyElem 的对组个数。对 map 来说,要么是 0,要么是 1。对
    multimap 来说,值可能大于 1lower_bound(keyElem);//返回第一个 key<=keyElem 元素的迭代器。
    upper_bound(keyElem);//返回第一个 key>keyElem 元素的迭代器。
    equal_range(keyElem);//返回容器中 key 与 keyElem 相等的上下限的两个迭代器。
    
    • 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

    10. unordered_set/multiset、unordered_map/multimap

           unordered_set/multiset、unordered_map/multimap是无序的,底层实现结构为哈希表(hash table),使用方法与8,9相似。唯独需要注意的就是unordered_set/multiset的元素是非C++内建类型时、unordered_map/multimap的key是非C++内建类型时,需要传入一个计算hash值的仿函数(hash function)
    alt

    //unordered_map模板定义
    template<//key:value
        class Key,//键值,key
        class T,//实值,value,
        class Hash = std::hash<Key>,//计算hash值,当key为C++内建类型时,有默认计算hash值得函数对象使用;否则需要自己传入计算hash值的新规则函数对象(仿函数)
        class KeyEqual = std::equal_to<Key>,//判断索引值相等的函数对象,与hash值类似,可能需要自定义
        class Allocator = std::allocator<std::pair<const Key, T>>
    >
    class unordered_map;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    #include 
    #include 
    #include 
     
    int main()
    {
        // 创建包含三个字符串的(映射到字符串的) unordered_map
        std::unordered_map<std::string, std::string> u =
        {
            {"红色", "#FF0000"},
            {"绿色", "#00FF00"},
            {"蓝色", "#0000FF"}
        };
     
        // 用于打印键值对的辅助 lambda 函数
        auto print_key_value = [](const auto& key, const auto& value)
        {
            std::cout << "键:[" << key << "] 值:[" << value << "]\n";
        };
     
        std::cout << "遍历并打印 unordered_map 的键值对,显式指定类型:\n";
        for (const std::pair<const std::string, std::string>& n : u)
            print_key_value(n.first, n.second);
     
        std::cout << "\n通过 C++17 的结构化绑定来遍历并打印 unordered_map 的键值对:\n";
        for (const auto& [key, value] : u)
            print_key_value(key, value);
     
        // 向 unordered_map 中添加两项
        u["黑色"] = "#000000";
        u["白色"] = "#FFFFFF";
     
        std::cout << "\n通过键输出值:\n"
                     "红色的十六进制表示:[" << u["红色"] << "]\n"
                     "黑色的十六进制表示:[" << u["黑色"] << "]\n\n";
     
        std::cout << "通过以先前不存在的键使用 operator[] 来插入新的键值对:\n";
        print_key_value("新键", u["新键"]);
     
        std::cout << "\n通过使用 auto 来遍历并打印键值对;\n"
                     "现在`新键`是映射中的一个键:\n";
        for (const auto& n : u)
            print_key_value(n.first, n.second);
    }
    
    • 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
    //unordered_set模板定义
    template<
        class Key,//元素的类型
        class Hash = std::hash<Key>,//计算hash值,当key为C++内建类型时,有默认计算hash值得函数对象使用;否则需要自己传入计算hash值的新规则函数对象(仿函数)
        class KeyEqual = std::equal_to<Key>,//判断索引值相等的函数对象,与hash值类似,可能需要自定义
        class Allocator = std::allocator<Key>//空间分配器,一般情况下无需修改
    >
    class unordered_set;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    //unordered_set示例
    #include 
    #include 
     
    void print(const auto& set)
    {
        for (const auto& elem : set)
            std::cout << elem << ' ';
        std::cout << '\n';
    }
     
    int main()
    {
        std::unordered_set<int> mySet{2, 7, 1, 8, 2, 8}; // 创建 int 的集合
        print(mySet);
     
        mySet.insert(5); // 将元素 5 加入集合
        print(mySet);
     
        if (auto iter = mySet.find(5); iter != mySet.end())
            mySet.erase(iter); // 移除 iter 指向的元素
        print(mySet);
     
        mySet.erase(7); // 移除元素 7
        print(mySet);
    }
    
    • 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

    11. 容器使用时机

    • vector 的使用场景:比如软件历史操作记录的存储,我们经常要查看历史记录,比如上一次的记录,上上次的记录,但却不会去删除记录,因为记录是事实的描述。
    • deque 的使用场景:比如排队购票系统,对排队者的存储可以采用 deque,支持头端的快速移除,尾端的快速添加。如果采用 vector,则头端移除时,会移动大量的数据,速度慢。
    • vector 与 deque 的比较
      (1)vector.at()比 deque.at()效率高,比如 vector.at(0)是固定的,deque 的开始位置
      却是不固定的。
      (2)如果有大量释放操作的话,vector 花的时间更少,这跟二者的内部实现有关。
      (3)deque 支持头部的快速插入与快速移除,这是 deque 的优点。
    • list 的使用场景:比如公交车乘客的存储,随时可能有乘客下车,支持频繁的不确实位置元素的移除插入。
    • set 的使用场景:比如对手机游戏的个人得分记录的存储,存储要求从高分到低分的顺序排列。
    • map 的使用场景:比如按 ID 号存储十万个用户,想要快速要通过 ID 查找对应的用户。二叉树的查找效率,这时就体现出来了。如果是 vector 容器,最坏的情况下可能要遍历完整个容器才能找到该用户。

    在这里插入图片描述

    
    
    
    
    • 1
    • 2
    • 3
  • 相关阅读:
    PTC:需求管理是智能汽车高效创新的关键能力
    Python实现的《芳华》WordCloud词云+LDA主题模型
    【人工智能】知识图谱
    qt -tablewidget设置列可排序
    小红书达人怎么对接,博主沟通流程汇总!
    【Vulfocus靶场-初级】Tomcat后台弱口令+War包文件上传Getshell漏洞复现
    在LMMS中导入mid文件并播放
    @Autowired注解和@Resource注解的区别
    日常SRC中xss小tips
    “大数据分析师”来了,提高职业含金量,欢迎来领
  • 原文地址:https://blog.csdn.net/weixin_44248258/article/details/133814790