​ C++ 对模板(Template)支持得很好,STL 就是借助模板把常用的数据结构及其算法都实现了一遍,并且做到了数据结构和算法的分离。STL提供了以下三种数据结构的实现:

  1. 顺行性容器
    • vector
    • deque
    • list
  2. 关联容器
    • set
    • muitiset
    • map
    • multipmap
  3. 容器适配器
    • stack
    • queue
    • priority_queue

Vector

Vector的创建

​ vector 是一个可以自动改变长度的数组。可以非常友好的的用来以邻接表的方式存储图。

//引入需要的头文件
#include <vector>
using namespace std;

//定义
vector <类型名> 变量名;

类型可以是int double char struct 也可以是STL容器,如vector,set,queue。

其中

vector<vector<类型> > 变量名     //表示一个二维数组 

Vector的初始化

vector<int> a //初始化一个不确定元素个数的数组
    
vector<int> a(10) //定义了10个整形元素的向量(数组),但没有给出初始值,因此其值是不确定的
    
vector<int> a(10,1) //定义了10个整形元素,且每个元素的初始值未1
    
vector<vector<int> > a(M, vector<int>(N,1))//定义了一个M行N列的二维数组,初始值为1
    
vector<vector<int> > a(M) //初始化一个M行列数不确定的数组

vector<vector<int> > a //初始化一个行列都不确定的数组

vector<int> a[100] //初始化了一个行可以自动分配,列不可以自动分配的数组
    
/*
注意:
vector<int> a;
for(int i=0;i<10;i++)
    a[i]=i;
这样使用是错误的,由于下标只能用于获取已经存在的数组,所以要这样使用的话,应该要先初始化数组
*/

Vector的函数

  1. 插入
a.insert(a.begin(), 3)    //在头部插入3
a.insert(a.end(), 2)      //在尾部加入2
a.push_back(x)            //尾部插入
  1. 删除
a.pop_back()          //删除最后一个元素,会使得容器长度(size)减短,但容器容量(capacity)不会变。
a.erase(a.begin())             //删除指定位置的元素
    
  1. 大小
a.size()             //容器中数据长度
a.capacity           //容器的长度

List

List的创建

​ lsit —— 双向循环列表容器双链表既可以向前又向后链接他的元素。每一个元素都知道前面一个元素和后面一个元素。

image-20221124111201363

list 容器具有一些其它容器(array、vector 和 deque)所不具备的优势,即它可以在序列已知的任何位置快速插入或删除元素(时间复杂度为O(1))。并且在 list 容器中移动元素,也比其它容器的效率高。

使用 list 容器的缺点是,它不能像 array 和 vector 那样,通过位置直接访问元素。

//引入需要的头文件
#include <list>
using namespace std;

//定义
list <类型名> 变量名; 
list<A> Listname(size,value);

List操作


    l.insert(position, n, ele) 					//插入一个元素到list中
    l.push_back() 				//在list的末尾添加一个元素 
    l.push_front() 				//在list的头部添加一个元素
    

    l.clear() 					//清空list的所有元素
    l.erase() 					//删除一个元素
    l.erase(l.begin(),l.end())  //将l从begin()到end()之间的元素删除。
    l.pop_back() 				//删除最后一个元素 
    l.pop_front() 				//删除第一个元素
    l.remove() 					//从list删除指定元素 
    l.unique() 					//删除list中重复的元素
    
    l.resize() 					//改变list的大小
    l.reverse() 				//把list的元素倒转
    

    l.front() 					//返回第一个元素 
    l.back() 					//返回最后一个元素
    l.empty() 					//若list是空的则返回true,否则返回false
    l.max_size() 				//返回list能容纳的最大元素数量 
    l.size() 					//返回list中的元素个数


    l.assign() 					//给list赋值
    l.get_allocator() 			//返回list的配置器
    l.merge() 					//合并两个list
    l.begin() 					//返回指向第一个元素的迭代器 
    l.end() 					//返回末尾的迭代器
    l.rbegin() 					//返回指向第一个元素的逆向迭代器 
    l.rend() 					//指向list末尾的逆向迭代器
    l.sort() 					//给list排序
    l.splice() 					//合并两个list
    l.swap() 					//交换两个list

List的使用

  • 遍历list
/*遍历一*/
     list<int>row;             //定义list 
     list<int>::iterator p1;        //定义迭代器 用于遍历 
     cout<<"请输入数据个数:";
     int n;
     cin>>n; 

     //输入值
     int j;
     for(j=0;j<n;j++) {
         int data;
         cin>>data;
         row.push_back(data);     //push_back()从list的末端插入一个元素 
     }

/*遍历二*/
     list<list<int>>l1;             //定义外层list 
     list<int>row;                  //定义内层list
     list<int>::iterator p1;        //定义迭代器 用于遍历内层元素 
     list<list<int>>::iterator p2;  //定义迭代器 用于遍历外层元素 
     cout<<"请输入行数:";
     int n;   //行数 
     cin>>n;
     //输入值 
      int i,j;
     for(i=0;i<n;i++){
     	row.clear();               //清空list 
     	cout<<"当前第"<<i+1<<"行,请输入该行数据"<<endl;
     	for(j=0;j<i+1;j++) {
          int data;
          cin>>data;
          row.push_back(data);     //push_back()从row的末端插入一个元素
        }
        l1.push_back(row);         //push_back()从l1的末端插入一个元素
        } 
          
     //外层迭代器 遍历list<list<int>> l1
     for(p2=l1.begin();p2!=l1.end();p2++){
     	list<int> ls = *p2;
     	//内层迭代器 遍历list<int> row
     	for(p1=ls.begin();p1!=ls.end();p1++){
        cout<< *p1 <<" ";
        }
        cout<<endl;
    }
    

/*遍历三*/
     //遍历值   
     cout<<"list:";
     for(p1=row.begin();p1!=row.end();p1++){
        cout<< *p1 <<" ";
     }	
    for (auto& e : lt)
        cout << e << " ";
    cout << endl;

//begin()是返回第一个值的迭代器,end()是返回指向容器中的最后一个元素下一个位置的迭代器(即头节点)
  • 其他用法
//list不能随机访问容器中的值,即不能it+n这样的操作。只能一个一个的走,即it++,因此遍历list需要用迭代器
list<int>::iterator it = l.begin();
while(it!=l.end()){
    cout<<*it<<" ";
    it++;
}

//用for遍历
    list<int> lt;
    lt.push_back(1);
    lt.push_back(2);
    lt.push_back(3);
    for (auto it = lt.begin(); it != lt.end(); it++)
        cout << *it << " ";
    cout << endl;
    for (auto& e : lt)     //auto是根据类型的初始值来定义类型的相当于迭代器
        cout << e << " ";
    cout << endl;


//要想删除一个区间段。只能用迭代器++一步一步的指向那个末尾位置,不能直接l.begin()+n
    list<int>::iterator it_begin = l.begin();
    list<int>::iterator it_end = l.begin();
    it2++;
    it2++;
    it2++;

    l.erase(it1, it2);		//删掉的是区间[it1,it2) 

Queue

Queue的创建

​ queue是一种容器模板,即可使用队列类(专门用于FIFO), 只能在容器的末尾添加新元素,只能从头部移除元素。

//引入需要的头文件
#include <queue>
using namespace std;

//定义
queue <类型名> 变量名;    //因为queue转换器要求容器支持front()、back()、push_back()及 pop_front(),说明queue的数据从容器后端入栈而从前端出栈。所以可以使用deque和list对queue初始化,而vector因其缺少pop_front(),不能用于queue。

Queue操作

front() //返回第一个元素
back()  //返回最后一个元素
push()  //队尾插入一个元素
pop()   //删除队列第一个元素
size()  //返回元素的个数
empty() //判断是否为空

Stack

Stack创建

专门进行LIFO的操作,即元素只从容器的一端插入和提取。

#include<stack>

stack<int> s; //定义栈

Stack操作

size();   //返回元素数目
push();   //栈顶增加元素
pop();    //移除栈顶元素
top();    //返回栈顶元素
empty();  //判断是否为空