$$ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Self-defined math definitions %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Math symbol commands \newcommand{\intd}{\,{\rm d}} % Symbol 'd' used in integration, such as 'dx' \newcommand{\diff}{{\rm d}} % Symbol 'd' used in differentiation ... $$

STL

  STL 是Standard Template Library的缩写,它是C++标准库的一部分,提供了许多常用的数据结构和算法,包括容器、迭代器、算法等。通过使用STL,可以更加方便灵活的处理数据。STL组成如下表。

类型 功能
容器 一些常用数据结构的模板类
算法 一些常用算法的模板类
迭代器 在STL中,对容器中元素的各种操作通过迭代器完成
函数对象 如果一个类将 () 运算符重载为成员函数,这个类就称为函数对象类,这个类的对象就是函数对象(又称仿函数)
适配器 可以使一个类的接口(模板的参数)适配成用户指定的形式,从而让原本不能在一起工作的两个类工作在一起
内存分配器 为容器类模板提供自定义的内存申请和释放功能

迭代器

  对于容器的各种操作,都必须使用迭代器完成。迭代器和指针类似,可以指向容器中的任意一个元素,进而对元素进行各种操作。其中STL定义的五种迭代器,如下表。需要注意的是:容器适配器 stack 和 queue 没有迭代器,它们包含有一些成员函数,可以用来对元素进行访问

迭代器类型 功能 适用容器
前向迭代器 前向迭代器 p 支持 ++p,p++,*p 操作,还可以被复制或赋值,可以用 == 和 != 运算符进行比较 forward_list
双向迭代器 除了支持前向迭代器的所有操作之外,还支持--p 或者 p-- 操作 list,map,set
随机访问迭代器 除了支持前向迭代器的所有操作之外,还支持p+=i,p-=i,p+i,p-i等操作。 array,vector,deque
输入迭代器 输入迭代器可用于读取容器中的元素,但是不保证能支持容器的写入操作 -
输出迭代器 输出迭代器可视为与输入迭代器功能互补的迭代器; 输出迭代器可用于向容器写入元素,但是不保证能支持读取容器内容 -

  常见的迭代器定义方式有两种:正向迭代器:容器类名::iterator  迭代器名;反向迭代器:容器类名::reverse_iterator  迭代器名。

容器

  容器,简单来讲,就是数据结构的一个模板。其中,STL主要有两种容器,序列容器和关联式容器。二者具体的关系如下表。

 序列式容器

   所谓序列式容器,指的就是用于保存int,char,double等类型数据的,以线性方式排列的的模板。序列容器插入的数据都会插在尾部,所以为了保证删除和插入的时间复杂度,一般都在尾部进行操作。(即数据插入的顺序就是数据保存的顺序)

array<T,N>(数组容器)

  数组容器表示可以存储N个T类型的元素,该类容器一旦建立,其长度就是固定不变的,不允许增加和删除元素,只能改变元素的值。

#include<iostream>
#include<array> //使用array容器需要array头文件
using namespace std;

int main(){
//定义两个array容器
    array<int, 5>   num_array;
    array<char, 3>  char_array {'a', 'b', 'c'};     //初始化char_array
    
//通过输入来初始化num_array
    cout << "Initialize the num_array" << endl;
    for(int i = 0; i < num_array.max_size(); i++){
        
        cin >> num_array[i];
    }
    
//使用容器名[]的方式直接访问元素
    cout << num_array[0] << endl;
    cout << char_array[0] << endl;
    
//使用at()函数访问,避免越界访问
    cout << num_array.at(0) + num_array.at(2) << endl;
//    cout << num_array.at(5) << endl;

//使用data函数获取首个元素的地址
    cout << *(num_array.data()) << endl;
    cout << *(num_array.data() + 1) <<endl;
   
//使用size函数返回容器中的元素
    for(size_t i = 0; i < char_array.size(); i++){
        cout << char_array[i] << "\t";
    }
    cout << endl;
    
//使用迭代器返回容器中的元素
    for(auto i = num_array.begin(); i < num_array.end(); i++){
        cout << *i << "\t";
    }
     return 0;
}
vector<T>(向量容器)

  用来存放 T 类型的元素,是一个长度可变的序列容器、使用此容器,在尾部增加或删除元素的效率最高。

#include<iostream>
#include<vector>
using namespace std;

int main(void){
    vector<int> vector_int;                            //初始化空的int型vector容器
    vector<double> vector_double(5, 1.00);            //初始化具有5个初始值为1.0元素的double型vector容器
    vector<char> vector_char {'a', 'b', 'c', 'd'};    //初始化含有abcd四个元素的char型vector容器
    
/*向vector中添加元素的唯一方式是使用vector的成员函数,push_back() & emplace_back()*/
    vector_int.push_back(1);
    vector_int.push_back(2);
    vector_int.emplace_back(3);
    vector_int.emplace_back(4);
    cout << "elements of vector_int are: ";
    for(auto i = vector_int.begin(); i < vector_int.end(); i++)
        cout << *i ;
    cout << endl;    
    
/*向vector中插入元素使用Vector的成员函数 insert() & emplace()*/
    vector_int.insert(vector_int.begin(), 0);        //在vector_int.begin()位置之前插入元素0
    vector_int.insert(vector_int.end(), 2, 5);        //在vector_int.end()位置之前插入两个元素5
    vector_int.insert(vector_int.end(), {6, 7, 8});    //在vector_int.end()位置之前插入6,7,8
    cout << "elements of new vector_int are: ";
    for(int i = 0; i < vector_int.size(); i++)
        cout << vector_int[i];
    cout << endl << endl;
    
/*删除vector中的元素也是使用vector的成员函数*/
    cout << "elements of vector_double are: ";
    for(int i = 0; i < vector_double.size(); i++)
        cout << vector_double[i];
    cout << endl;
    vector_double.pop_back();                        //删除vector_double中的最后一个元素
    vector_double.erase(vector_double.begin());        //删除.begin()位置上的元素
    cout << "elements of new vector_double are: ";
    for(int i = 0; i < vector_double.size(); i++)
        cout << vector_double[i];
    /*capacity指给当前所能容纳最大元素数,size指当前容器实际容纳元素数*/
    cout << endl << "vector_double.capacity: " <<vector_double.capacity() << endl;
    cout << "vector_double.size: " << vector_double.size() << endl << endl;
    
/*swap函数可以交换任意两个容器的元素*/
    swap(*(vector_char.begin()), *(vector_char.end()-1));//交换第一个和第四个元素
    cout << vector_char.size();
    cout << "vector_char: ";
    for(auto i = vector_char.begin(); i < vector_char.end(); i++)
        cout << *i;
    cout << endl;
    vector<char> new_vector_char;
    new_vector_char.swap(vector_char);
    cout << "elements of new_vector_char are: ";
    for(auto && i : new_vector_char)
        cout << i;
    cout << endl;
    
    return 0;
}

deque<T>(双端队列容器)

  使用该容器不仅尾部插入和删除元素高效,在头部插入或删除元素也同样高效,时间复杂度都是 O(1) 常数阶。

#include<iostream>
#include<deque>
using namespace std;

int main(void){
    deque<int>    deque_int;                        //初始化空的int型双端队列
    deque<double> deque_double(5, 2.0);                //初始化有5个元素初值为2.0的双端队列
    deque<char>   deque_char {'a', 'b', 'c', 'd'};    //初始化有abcd的双端队列
/*对deque_int进行赋初值的操作*/
    deque_int.push_front(0);                        //在头部添加元素0
    deque_int.push_front(1);                        //在头部添加元素1
    deque_int.push_back(2);                            //在尾部添加元素2
    deque_int.push_back(3);                            //在尾部添加元素3
    deque_int.emplace_front(5);                        //在头部添加元素5
    deque_int.emplace_back(6);                        //在尾部添加元素6
    cout << "elements of deque_int are: ";
    for(auto i = deque_int.begin(); i < deque_int.end(); i++)
        cout << *i;
    cout << endl << endl;
    
    cout << "elements of deque_double are: ";
    for(int i = 0; i < deque_double.size(); i++)
        cout << deque_double[i];
    cout << endl;
    deque_double.insert(deque_double.begin()+1, 3.1);//在第二个位置之前插入元素3.1
    deque_double.emplace(deque_double.end()-1, 4.5); //在最后一个元素之前位置插入4.5
    cout << "elements of altering deque_double are: ";
    for (auto i = deque_double.begin(); i < deque_double.end(); i++) {
        cout << *i << " ";
    }
    cout << endl << endl;
    
    cout << "elements of deque_char are: ";
    for(int i = 0; i < deque_char.size(); i++)
        cout << deque_char[i];
    cout << endl;
    deque_char.pop_back();                            //删除最后一个元素
    deque_char.pop_front();                            //删除头一个元素
    deque_char.erase(deque_char.begin());            //删除指定位置的元素
    cout << "elements of altering deque_char are: ";
    for(auto i = deque_char.begin(); i < deque_char.end(); i++)
        cout << *i;
    cout << endl << endl;
    
    return 0;
}

 list<T>(链表容器)

  该容器是一个长度可变的、由 T 类型元素组成的序列,它以双向链表的形式组织元素,可以增删任意一个元素,但是访问元素必须在链头或链尾开始。

#include<iostream>
#include<list>
using namespace std;

int main(void){
    list<int> list_int;                            //初始化空的int型list容器
    list<double> list_double(5, 1.00);            //初始化具有5个初始值为1.0元素的double型list容器
    list<char> list_char {'a', 'b', 'c', 'd'};    //初始化含有abcd四个元素的char型list容器

/*向list_int中插入元素*/    
    list_int.push_front(0);                        //在头部添加元素0
    list_int.push_front(1);                        //在头部添加元素1
    list_int.push_back(2);                         //在尾部添加元素2
    list_int.push_back(3);                         //在尾部添加元素3
    list_int.emplace_front(5);                     //在头部添加元素5
    list_int.emplace_back(6);                      //在尾部添加元素6
    cout << "elements of list_int are: ";
    for(auto i = list_int.begin(); i != list_int.end(); i++)
        cout << *i;
    cout << endl << endl;
    
/*向list_double中插入元素*/
    cout << "elements of list_double are: ";
    for (auto i = list_double.begin(); i != list_double.end(); i++) {
        cout << *i << " ";
    }
    cout << endl;
    list_double.insert(list_double.begin(), 3.1);//在第二个位置之前插入元素3.1
    list_double.emplace(list_double.end(), 4.5); //在最后一个元素之前位置插入4.5
    cout << "elements of altering list_double are: ";
    for (auto i = list_double.begin(); i != list_double.end(); i++) {
        cout << *i << " ";
    }
    cout << endl << endl;
    
/**/
    cout << "elements of list_char are: ";
    for(auto i = list_char.begin(); i != list_char.end(); i++)
        cout << *i;
    cout << endl;
    list_char.pop_back();                           //删除最后一个元素
    list_char.pop_front();                          //删除头一个元素
    list_char.erase(list_char.begin());                //删除指定位置的元素
    list_char.insert(list_char.begin(), 3, 'e');    //插入三个相同的元素e
    list_char.remove('e');                            //删除所有e
    cout << "elements of altering list_char are: ";
    for(auto i = list_char.begin(); i != list_char.end(); i++)
        cout << *i;
    cout << endl << endl;
    return 0;
}
forward_list<T>(正向链表容器)

  该容器和 list 容器非常类似,只不过它以单链表的形式组织元素,它内部的元素只能从第一个元素开始访问。

#include<iostream>
#include<forward_list>
using namespace std;

int main(void){
    forward_list<int> forward_list_int;                            //初始化空的int型forward_list容器
    forward_list<char> forward_list_char {'a', 'b', 'c', 'd'};    //初始化含有abcd四个元素的char型forward_list容器
    
    forward_list_int.push_front(0);                        //在头部添加元素0
    forward_list_int.push_front(1);                        //在头部添加元素1
    forward_list_int.emplace_front(2);                       //在头部添加元素2
    forward_list_int.emplace_front(3);                       //在头部添加元素3   
    for(auto i = forward_list_int.begin(); i != forward_list_int.end(); i++)
        cout << *i;
    cout << endl << endl;
    
    cout << "elements of forward_list_char are: ";
    for(auto i = forward_list_char.begin(); i != forward_list_char.end(); i++)
        cout << *i;
    cout << endl;
    forward_list_char.pop_front();                            //删除头部元素
    auto it = forward_list_char.begin();
    while (it!=forward_list_char.end())
    {
        cout << *it;
        ++it;
    }
    return 0;
}

关联式容器

  关联式容器在存储元素的值的同时,还会为每一个元素配备一个额外的值,又称之键“ key ”。关联式容器的优点在于只要知道某一个元素的键,就可以直接通过该键的值直接找到目标元素,而无需遍历整个容器。即关联式容器按照<key, value>的方式存储元素。序列式容器按照元素输入顺序存储元素。

  pair类模板:C++ STL提供了pair类模板将两个元素组合成<key, value>类型的元素。

#include<iostream>
#include<utility>
#include<string>
using namespace std;

int main(void){
    
    pair <string, string> pair1("key", "value");
    pair <string, string> pair2("key2", "value2");
    
    cout << "pair1: " << pair1.first << " " << pair1.second << endl;
    cout << "pair2: " << pair2.first << " " << pair2.second << endl;
    return 0;
}
map

  一般情况下,map容器中存储的各个键值对都选用string字符串作为键的类型。在使用map容器存储多个键值对时,该容器会自动根据各键值对的键的大小,按照既定的规则进行排序。默认根据键值大小做升序排序。

set
multimap
multiset

  

算法 

参考资料

[1] STL,C语言中文网,http://c.biancheng.net/stl/。

posted @ 2023-04-09 09:48  素衣叹风尘  阅读(31)  评论(0)    收藏  举报