STL容器(Stack, Queue, List, Vector, Deque, Priority_Queue, Map, Pair, Set, Multiset, Multimap)

时间:2021-05-17 09:24:51

一、Stack(栈)

  • 这个没啥好说的,就是后进先出的一个容器。
  • 基本操作有:
     stack<int>q;
q.push(); //入栈
q.pop(); //出栈
q.top(); //返回栈顶成员
q.size(); //返回栈成员个数
q.empty(); //判断是否为空栈

二、Queue(队列)

  • 同上,先进先出的容器
  • 基本操作有:
     queue<int>q;
q.push(); //入队列
q.pop(); //出队列
q.front(); //返回最上面(最后进入)的成员
q.size(); //返回队列成员个数
q.empty(); //判断是否为空队列

三、Priority_Queue(优先队列)

  • priority_queue的模板生命是带有三个参数的:priority_queue<type,container,function>
  • 和队列差不多,不过每个成员都有一个优先级参数,队列按照优先级进行排序
  • 默认container是vector,默认function比较模式为operator <(即栈顶为最大值)。
  • 基本操作有:
     priority_queue<int,vector<int>,greater<int> >q;
q.push(); //入优先队列
q.top(); //返回优先队列头成员
q.pop(); //出优先队列
q.size(); //返回优先队列成员个数
q.empty(); //判断是否为空优先队列
  • 内置的排序方式有greater<>,和less<>,不填此参数默认为greater<>。当然也可以自己构造优先级函数
  • 例如对结构体重载运算符:
     struct node{
int x,y; //重载运算符,按x的值排优先级
friend operator < (node a,node b){
return a.x < b.x;
}
};
  • 也可以将重载操作写在外面,优先队列中调用cmp函数
     struct node{
int x,y;
};
struct cmp{
//重载运算符,按x的值排优先级
bool operator() (node a,node b){
return a.x < b.x;
}
}; priority_queue<node,vector<node>,cmp >q;

四、Deque(双向队列)

  • 一听就知道和Queue差不多 ,特殊的是Deque可是扩充内存。我们知道连续内存的容器不能随意扩充,所以Deque也不是真正意义上的扩充内存。
  • Deque是由一段一段构成的,当走到尾端时自动跳到下一段,(支持迭代器++操作)。每次扩充,申请一个段,实现了内存连续的假象。
  • 基本操作有:
     int num[] = {,,,,,};
deque<int>q; //创建一个空双向队列
deque<int>p(); //创建一个具有5个成员的双向队列
deque<int>s(,); //创建一个具有5个成员且初始值为1的双向队列
deque<int>s2(s); //创建一个双向队列s2,并拷贝s中所有成员
deque<int>n(num,num+); //创建一个双向队列n,并拷贝num至num+5中元素入队 q.push_front(a); //头部入队
q.pop_back(b); //尾部入队
q.insert(iter,x); //在iter位置插入x,iter为迭代器
q.pop_front(); //头部出队
q.pop_back(); //尾部出队 q.front(); //返回头成员
q.back(); //返回尾元素
q.size(); //返回双向队列成员个数
q.max_size(); //返回系统支持成员最大个数
q.empty(); //判断双向队列是否为空 q.at(i); //返回第i个元素
q.begin(); //返回头部迭代器
q.end(); //返回尾部迭代器
q.rbegin(); //返回尾部反向迭代器
q.rend(); //返回头部反向迭代器 q.erase(iter); //删除iter元素,iter为迭代器
q.clear(); //情况双向队列
q.swap(p); //交换q和p中的所有元素
  • Deque采用分块线型结构存储数据,两个迭代器分别指向首尾元素,而且拥有具有高效的push_back(),push_front()函数。
  • 正因如此,所以Deque不易实现capacity和reverse函数。
  • Deque的缺点:频繁的插入删除时候,Deque并不适合。

五、Vector(动态数组)

  • 顾名思义,不定长数组。
  • uhmmm没啥好说的
  • 基本操作有:
     vector<int>q;           //创建空Vector
vector<int>p(); //创建拥有5个成员的Vector
vector<int>s(,); //创建拥有5个成员,且初始值为1的Vector
vector<int>s2(s); //创建s2,并拷贝s元素给s2
vector<int>s3(s.begin(),s.end()); //创建s3,拷贝s.begin()至s.end()中元素给s3 q.push_back(x); //尾部加入元素
q.insert(iter,x); //在iter位置插入x,传回新数据位置
q.insert(iter,n,x); //在iter位置插入n个x,无返回值
q.insert(iter,l,r); //在iter位置插入[l,r)区间内的数据,无返回值
q.pop_back(); //删除最后一个元素
q.front(); //返回第一个数据
q.back(); //返回最后一个数据 q.size(); //返回容器内成员个数
q.resize(x); //重新指定容器大小
q.empty(); //判断Vector是否为空
q.capacity(); //返回Vector可用空间的大小
q.reserve(); //重新指定空间大小,小于当前capacity时保持为原本的capacity值
q.swap(p); //交换p,q容器内元素
q.assign(iter1,iter2); //将区间[iter1,iter2)内元素赋值给vector,并清空vector容器之前的内容。
q.assign(n,x); //将n个x赋值到vector中,并清空vector容器之前的内容。 q.at(i); //返回第i个元素
q.begin(); //返回头位置迭代器
q.end(); //返回尾位置迭代器
q.rbegin(); //返回尾部反向迭代器
q.rend(); //返回头部反向迭代器 q.clear(); //情况Vector
q.erase(); //删除iter位置元素
q.erase(iter1,iter2); //删除[iter1,iter2)区间内的元素
  • 此外,vector还可以用数组的方式引用,因为以及内置重载了[],例如q[0]等同于q.at(1)。

六、List(链表)

  • 链表其实用的不多
  • 自己也没怎么用过 =7= 直接放代码操作了
  • 基本操作:
     list<int>q;           //创建空List
list<int>p(); //创建拥有5个成员的List
list<int>s(,); //创建拥有5个成员,且初始值为1的List
list<int>s2(s); //创建s2,并拷贝s元素给s2
list<int>s3(s.begin(),s.end()); //创建s3,拷贝s.begin()至s.end()中元素给s3 q.back() //返回最后一个元素
q.begin() //返回指向第一个元素的迭代器
q.clear() //删除所有元素
q.empty() //如果list是空的则返回true
q.end() //返回末尾的迭代器
q.erase() //删除一个元素 q.front() //返回第一个元素
q.get_allocator() //返回list的配置器
q.insert() //插入一个元素到list中
q.max_size() //返回list能容纳的最大元素数量
q.merge() //合并两个list
q.pop_back() //删除最后一个元素
q.pop_front() //删除第一个元素
q.push_front() //在list的头部添加一个元素 q.rbegin() //返回指向第一个元素的逆向迭代器
q.remove() //从list删除元素
q.remove_if() //按指定条件删除元素
q.rend() //指向list末尾的逆向迭代器
q.resize() //改变list的大小
q.reverse() //把list的元素倒转
q.size() //返回list中的元素个数
q.sort() //给list排序
q.splice() //合并两个list
q.swap() //交换两个list
q.unique() //删除list中重复的元素

七、Pair(对)

  • 就是合成两个数据,这个用结构体模拟也行,但是直接使用Pair会方便很多
  • 基本操作如下:
     pair<int,int>q;     //创建一个空对
pair<int,int>p(,);//创建一个对p,并分别赋值2,3
pair<int,int>s(p); //创建一个对s,拷贝p给s //赋值利用make_pair函数
q = make_pair(,);
//访问pair内元素操作
q.first; //返回成员第一个数据
q.second; //返回成员第二个数据

八、Set(集合)

  • 首先Set遵循数学集合三特性,无重复、无序性、确定性。我就不解释了。
  • Set中内置红黑树进行排序,所以插入删除效率很高。
  • 常用操作如下:
     int a[] = {,,,,};
set<int>q;
set<int>p; q.insert(x); //集合中插入元素
q.insert(a,a+); //插入数组a至a+5的元素
q.find(x); //返回x值位置的迭代器,找不到返回q.end()
q.erase(iter); //删除集合中的元素
q.size(); //返回当前set容器中的元素个数
q.count(); //返回某个值元素的个数(根据set的特性,就是判断这个元素在不在,返回0或1)
q.begin(); //返回头位置迭代器
q.end(); //返回尾位置迭代器
q.rbegin(); //返回尾部反向迭代器
q.rend(); //返回头部反向迭代器
q.clear(); //删除set容器中的所有的元素
q.empty(); //判断set容器是否为空
q.lower_bound(); //返回指向大于(或等于)某值的第一个元素的迭代器
q.upper_bound(); //返回大于某个值元素的迭代器
  • 当然,你也可以自定义Set内部的排序操作,例如:
     struct cmp{
bool operator() (const node &a,const node &b){
return a.x < b.x;
}
}; set<node,cmp>q;

九、Map

  • 不知道该翻译成啥,干脆不翻译了 =7=
  • map是一种关联容器,例如map<int,int>,第一个元素可以称为关键字,类似数组的下标,不会重复出现,而第二个元素为关键字的值,类似数组中存的元素,可以重复。
  • map不能直接修改关键字,只能通过修改关键字的值间接修改关键字。
  • 和Set一样,map也是内置红黑树对关键字进行排序。能够实现快速查找和删除功能。
  • 基本操作:
     map<int,int>q;

     q.insert(pair<int,int>(,));       //通过pair进行插入操作
q.insert(map<int,int>::value_type (,));//通过value_type进行插入
q[] = ; //用数组方式进行插入
/*三者不同的是,当map存在这个关键字时
*数组方式会覆盖关键字的值,而insert操作无法插入。
*/ q.size(); //返回容器内元素个数
q.empty(); //判断容器是否为空
q.begin(); //返回头位置迭代器
q.end(); //返回尾位置迭代器
q.rbegin(); //返回尾部反向迭代器
q.rend(); //返回头部反向迭代器
q.find(key); //查找并返回关键字key的位置
q.count(key); //查询是否有关键字key(有则返回1,否则0)
q.lower_bound();//返回键值>=给定元素的第一个位置
q.upper_bound();//返回键值>给定元素的第一个位置
q.erase(iter); //删除迭代器iter的元素
q.erase(iter1,iter2);//删除[iter1,iter2)区间内的元素
q.erase(key); //删除关键字为key的元素
q.clear(); //清空容器
q.swap(p); //交换两个map
q.key_comp(); //返回比较元素key的函数
q.max_size(); //返回可以容纳的最大元素个数
q.value_comp(); //返回比较元素value的函数
q.equal_range();//返回特殊条目的迭代器对
  • 当然你可以自己写内部排序函数
  • 例如结构体中重载<号,或者编写仿函数,例如:
 class sort{

 public:
bool operator() (node const &a,node const &b) const{
return a.x < b.x;
} };

十、Multiset(多重集合)

  • 和Set不同的地方是Multiset允许一个值出现多次;
  • 操作和set相同。但是因为值能重复出现,所有某些函数的返回值将会改变,例如:
  • multiset::count(key)返回值可能大于1;(多个关键值存在)
  • multiset::erase(key)会将对应的key全部删掉。
  • 对于set总是有set::equal_range(key)的返回值总有++iter1 = iter2.但multiset不一定(元素相同)

十一、Multimap

  • 同上,和map类似,可以存在相同的关键字。

本来想讲BitSet,但是觉得bitset比较特殊,到时候专门详细讲吧。

其实所有容器都挺简单的,根据特性基本都能想出操作。熟悉了这些容器之后,对做题和学习很有帮助的。

记住操作没啥用,得不断的练习使用这些容器 ,才能熟练操作。

emmmm都说的很简陋,本来想讲每个容器的具体实现一起构造方式。后来一想,篇幅太长了,还容易误导别人觉得容器很复杂。这些都算是学个表面吧,最重要的还是不断敲敲敲,熟悉各种用法。

大致就这样吧 =7=


后续:Stack,Queue,Pair并不是C++的标准容器,但是我觉得性质差不多,就一起讲了,但是防止误导初学者,这里还是提一下。