首页 > 技术文章 > C++ 标准模板库(STL)——容器(Containers)的用法及理解

JCpeng 2021-07-12 09:31 原文

C++ 标准模板库(STL)中定义了通用的模板类和函数,这些模板类和函数可以实现多种流行和常用的算法和数据结构,如向量(vector)、队列(queue)、栈(stack)、set、map等。这次主要介绍C++ 标准模板库(STL)中常用的容器(管理某一类对象的集合)用法以及自己的理解。

一、向量(vector)

向量(vector)容器与数组十分相似,唯一不同的是,向量在需要扩展大小的时候,会自动处理它自己的存储需求。例如:

#include<iostream>
#include<vector>   //vector模板库
using namespace std;

int main()
{
    vector<int> int_vec;               //定义vector: vector <类型> 名称
    for (int i = 0; i < 5; i++)
    {
        int_vec.push_back(i);          //vector.push_back(): 从vector末尾加入一个元素
    }
    cout << int_vec.front() << endl;   //vector.front(): 返回vector当前第一个元素值
    cout << int_vec[2] << endl;        //vector[2]: 返回vector当前第三个元素值
    cout << int_vec.back() << endl;    //vector.back(): 返回vector当前最后一个元素值
    cout << int_vec.size() << endl;    //vector.size(): 返回vector当前的长度(大小)
    int_vec.pop_back();                //vector.pop_back(): 从vector末尾删除一个元素
    cout << int_vec.size() << endl;
    int_vec.clear();                   //vector.clear(): 清空vector
    if (int_vec.empty())               //vector.empty(): 返回vector是否为空,1为空、0不为空
    { 
        cout << "int_vec is empty !" << endl; 
    }
    return 0;
}

 注意:vector容器是支持随机访问的,即可以像数组一样用 [ ] 来取值;但不是所有的C++ STL容器都有这个性质。

二、队列(queue)与双向队列(deque)

与栈相反,队列(queue)是一种严格的“先进先出”数据结构;在C++ STL中队列容器的用法举例如下:

#include<iostream>
#include<queue>    //queue模板库
using namespace std;

int main()
{
    queue<char> char_que;                //定义queue: queue <类型> 名称
    for (int i = 0; i < 5; i++)
    {
        char_que.push( i + 'a');         //queue.push(): 从queue末尾加入一个元素
    }
    cout << char_que.front() << endl;    //queue.front(): 返回queue的队首元素
    cout << char_que.back() << endl;     //queue.back(): 返回queue的队尾元素
    cout << char_que.size() << endl;     //queue.size(): 返回queue当前的长度(大小)
    char_que.pop();                      //queue.pop(): 从queue末尾删除一个元素
    cout << char_que.back() << endl;
    cout << char_que.size() << endl;
    if (!char_que.empty())               //queue.empty(): 返回queue是否为空,1为空、0不为空
    {
        cout << "char_que is not empty!" << endl;
    }
    return 0;
}

注意:queue不支持随机访问,即不能像数组一样地任意取值。并且,queue并不支持全部的vector的内置函数。比如queue不可以用clear()函数清空,清空queue必须一个一个弹出。同样,queue也并不支持遍历,无论是数组型遍历还是迭代器型遍历统统不支持,所以没有begin(),end()函数。

双向队列(deque)与一般队列不同,他支持双向操作,即同时可以在队首或队尾插入或删除元素;同时,双向队列支持随机访问,即通过deque[index]访问。具体用法如下:

#include<iostream>
#include<queue>    //queue模板库
using namespace std;

int main()
{
    deque<char> char_deque;
    for (int i = 0; i < 5; i++)
    {
        char_deque.push_front(i + 'a');        //从deque末尾加入一个元素
        char_deque.push_back(i + 'A');         //从deque末尾加入一个元素
    }
    cout << char_deque.front() << endl;        //返回deque的队首元素
    cout << char_deque.back() << endl;         //返回deque的队尾元素
    cout << char_deque[3] << endl;             //返回deque下标为3的元素
    cout << char_deque.size() << endl;         //返回deque当前的长度(大小)
    char_deque.pop_front();                    //从deque首部删除一个元素
    char_deque.pop_back();                     //从deque末尾删除一个元素
    cout << char_deque.front() << endl;
    cout << char_deque.back() << endl;
    cout << char_deque.size() << endl;
    if (!char_deque.empty())                   //返回deque是否为空,1为空、0不为空
    {
        cout << "char_deque is not empty!" << endl;
    }
    return 0;
}

三、栈(stack)

栈(stack)是一种基本的“先进后出”数据结构,在C++ STL 中将栈模板化了;具体用法如下:

#include<iostream>
#include<stack>    //stack模板库
using namespace std;

int main()
{
    stack<int> int_stack;                  //satck定义:stack <变量类型> 名称
    for (int i = 0; i < 5; i++)
    {
        int_stack.push(i);                 //satck.push():从stack栈顶加入一个元素
    }
    for (int i = 0; i < 5; i++)
    {
        cout << int_stack.size() << endl;  //satck.size():返回stack当前的长度(大小)
        cout << int_stack.top() << endl;   //satck.top():返回stack的栈顶元素
        int_stack.pop();                   //satck.pop():从stack栈顶弹出一个元素
    }
    if (int_stack.empty())                 //satck.empty():返回stack是否为空,1为空、0不为空
    {
        cout << "int_stack is empty !" << endl;
    }
    return 0;
}

 事实上,C++ STL 中stack容器并不是一种标准的数据结构,它其实是一个容器适配器,里面还可以存其他的STL容器。

四、集合(set)

 set容器在C++ STL实现了这个集合的功用,它的功用就是维护一个集合,其中的元素满足互异性。即两两不同,如果这个setset容器中已经包含了一个元素i,那么无论我们后续再往里假如多少个i,这个set中还是只有一个元素i。其次,数学中的集合是有无序性的,但是set容器中的元素是默认排好序(按升序排列)的。其具体用法如下:

#include<iostream>
#include<set>        //set模板库
using namespace std;

int main()
{
    set<int> int_set;
    for (int i = 0; i < 5; i++)
    {
        int_set.insert(i);            //set.insert():向set中加入元素
    }
    for (auto start = int_set.begin(); start != int_set.end(); start++)
    {
                                      //set.begin()函数和set.end()函数返回set的首尾迭代器
        cout << *start << endl;
    }
    cout << int_set.size() << endl;   //set.size():返回当前set的元素个数
    auto it = int_set.find(2);        //set.find():返回set中指向元素k的迭代器。如果不存在这个元素,就返回set.end()
    cout << *it << endl;
    int_set.erase(2);                 //set.erase():向set中删除指定元素
    int_set.clear();                  //set.clear():清空当前set
    if (int_set.empty())              //set.empty():返回set是否为空,是返回1,否则返回0.
    {
        cout << "int_set is empty !" << endl;
    }
    return 0;
}

五、map

C++ STL中map是“映射容器”,其存储的两个变量构成了一个键值(key)到元素(value)的映射关系。具体用法如下:

#include<iostream>
#include<map>    //map模板库
using namespace std;

int main()
{
    map<int, char> my_map;                                   //map定义:map<类型, 类型> 名称
    my_map[0] = 'a';                                         //map[key] = value:map直接赋值
    my_map[1] = 'b';
    my_map.insert(map<int, char>::value_type(2, 'c'));       //map.insert():map插入元素
    auto it = my_map.find(2);                                //map.find():通过键值查找map中的指定元素
    cout << "key: " << it->first << " value: " << it->second << endl;
    my_map.erase('b');                                       //map.erase():删除map中的指定元素
    cout << my_map.size() << endl;                           //map.size():返回map元素个数
    for (auto it = my_map.begin(); it != my_map.end(); it++) //map.begin()、map.end():返回map的首、尾迭代器
    {
        cout << "key: " << it->first << " value: " << it->second << endl;
    }
    my_map.clear();                                          //map.clear():删除map所有元素
    if (my_map.empty())                                      //map.empty():返回map是否为空,为空返回1否则0
    {
        cout << "my_map is empty !" << endl;
    }
    return 0;
}

六、容器间的嵌套

(1)自身嵌套

vector<vector<int>> two_vec;

(2)交叉嵌套

stack<vector<int>>;

推荐阅读