STL容器(Stack, Queue, List, Vector, Deque, Priority_Queue, Map, Pair, Set, Multiset, Multimap)
一、Stack(栈)
- 这个没啥好说的,就是后进先出的一个容器。
- 基本操作有:
1 stack<int>q; 2 q.push(1); //入栈 3 q.pop(); //出栈 4 q.top(); //返回栈顶成员 5 q.size(); //返回栈成员个数 6 q.empty(); //判断是否为空栈
二、Queue(队列)
- 同上,先进先出的容器
- 基本操作有:
1 queue<int>q; 2 q.push(1); //入队列 3 q.pop(); //出队列 4 q.front(); //返回最上面(最后进入)的成员 5 q.size(); //返回队列成员个数 6 q.empty(); //判断是否为空队列
三、Priority_Queue(优先队列)
- priority_queue的模板生命是带有三个参数的:priority_queue<type,container,function>
- 和队列差不多,不过每个成员都有一个优先级参数,队列按照优先级进行排序
- 默认container是vector,默认function比较模式为operator <(即栈顶为最大值)。
- 基本操作有:
1 priority_queue<int,vector<int>,greater<int> >q; 2 q.push(1); //入优先队列 3 q.top(); //返回优先队列头成员 4 q.pop(); //出优先队列 5 q.size(); //返回优先队列成员个数 6 q.empty(); //判断是否为空优先队列
- 内置的排序方式有greater<>,和less<>,不填此参数默认为greater<>。当然也可以自己构造优先级函数
- 例如对结构体重载运算符:
1 struct node{ 2 int x,y; 3 4 //重载运算符,按x的值排优先级 5 friend operator < (node a,node b){ 6 return a.x < b.x; 7 } 8 };
- 也可以将重载操作写在外面,优先队列中调用cmp函数
1 struct node{ 2 int x,y; 3 }; 4 struct cmp{ 5 //重载运算符,按x的值排优先级 6 bool operator() (node a,node b){ 7 return a.x < b.x; 8 } 9 }; 10 11 priority_queue<node,vector<node>,cmp >q;
四、Deque(双向队列)
- 一听就知道和Queue差不多 ,特殊的是Deque可是扩充内存。我们知道连续内存的容器不能随意扩充,所以Deque也不是真正意义上的扩充内存。
- Deque是由一段一段构成的,当走到尾端时自动跳到下一段,(支持迭代器++操作)。每次扩充,申请一个段,实现了内存连续的假象。
- 基本操作有:
1 int num[] = {1,2,3,4,5,6}; 2 deque<int>q; //创建一个空双向队列 3 deque<int>p(5); //创建一个具有5个成员的双向队列 4 deque<int>s(5,1); //创建一个具有5个成员且初始值为1的双向队列 5 deque<int>s2(s); //创建一个双向队列s2,并拷贝s中所有成员 6 deque<int>n(num,num+5); //创建一个双向队列n,并拷贝num至num+5中元素入队 7 8 q.push_front(a); //头部入队 9 q.pop_back(b); //尾部入队 10 q.insert(iter,x); //在iter位置插入x,iter为迭代器 11 q.pop_front(); //头部出队 12 q.pop_back(); //尾部出队 13 14 q.front(); //返回头成员 15 q.back(); //返回尾元素 16 q.size(); //返回双向队列成员个数 17 q.max_size(); //返回系统支持成员最大个数 18 q.empty(); //判断双向队列是否为空 19 20 q.at(i); //返回第i个元素 21 q.begin(); //返回头部迭代器 22 q.end(); //返回尾部迭代器 23 q.rbegin(); //返回尾部反向迭代器 24 q.rend(); //返回头部反向迭代器 25 26 q.erase(iter); //删除iter元素,iter为迭代器 27 q.clear(); //情况双向队列 28 q.swap(p); //交换q和p中的所有元素
- Deque采用分块线型结构存储数据,两个迭代器分别指向首尾元素,而且拥有具有高效的push_back(),push_front()函数。
- 正因如此,所以Deque不易实现capacity和reverse函数。
- Deque的缺点:频繁的插入删除时候,Deque并不适合。
五、Vector(动态数组)
- 顾名思义,不定长数组。
- uhmmm没啥好说的
- 基本操作有:
1 vector<int>q; //创建空Vector 2 vector<int>p(5); //创建拥有5个成员的Vector 3 vector<int>s(5,1); //创建拥有5个成员,且初始值为1的Vector 4 vector<int>s2(s); //创建s2,并拷贝s元素给s2 5 vector<int>s3(s.begin(),s.end()); //创建s3,拷贝s.begin()至s.end()中元素给s3 6 7 q.push_back(x); //尾部加入元素 8 q.insert(iter,x); //在iter位置插入x,传回新数据位置 9 q.insert(iter,n,x); //在iter位置插入n个x,无返回值 10 q.insert(iter,l,r); //在iter位置插入[l,r)区间内的数据,无返回值 11 q.pop_back(); //删除最后一个元素 12 q.front(); //返回第一个数据 13 q.back(); //返回最后一个数据 14 15 q.size(); //返回容器内成员个数 16 q.resize(x); //重新指定容器大小 17 q.empty(); //判断Vector是否为空 18 q.capacity(); //返回Vector可用空间的大小 19 q.reserve(); //重新指定空间大小,小于当前capacity时保持为原本的capacity值 20 q.swap(p); //交换p,q容器内元素 21 q.assign(iter1,iter2); //将区间[iter1,iter2)内元素赋值给vector,并清空vector容器之前的内容。 22 q.assign(n,x); //将n个x赋值到vector中,并清空vector容器之前的内容。 23 24 q.at(i); //返回第i个元素 25 q.begin(); //返回头位置迭代器 26 q.end(); //返回尾位置迭代器 27 q.rbegin(); //返回尾部反向迭代器 28 q.rend(); //返回头部反向迭代器 29 30 q.clear(); //情况Vector 31 q.erase(); //删除iter位置元素 32 q.erase(iter1,iter2); //删除[iter1,iter2)区间内的元素
- 此外,vector还可以用数组的方式引用,因为以及内置重载了[],例如q[0]等同于q.at(1)。
六、List(链表)
- 链表其实用的不多
- 自己也没怎么用过 =7= 直接放代码操作了
- 基本操作:
1 list<int>q; //创建空List 2 list<int>p(5); //创建拥有5个成员的List 3 list<int>s(5,1); //创建拥有5个成员,且初始值为1的List 4 list<int>s2(s); //创建s2,并拷贝s元素给s2 5 list<int>s3(s.begin(),s.end()); //创建s3,拷贝s.begin()至s.end()中元素给s3 6 7 q.back() //返回最后一个元素 8 q.begin() //返回指向第一个元素的迭代器 9 q.clear() //删除所有元素 10 q.empty() //如果list是空的则返回true 11 q.end() //返回末尾的迭代器 12 q.erase() //删除一个元素 13 14 q.front() //返回第一个元素 15 q.get_allocator() //返回list的配置器 16 q.insert() //插入一个元素到list中 17 q.max_size() //返回list能容纳的最大元素数量 18 q.merge() //合并两个list 19 q.pop_back() //删除最后一个元素 20 q.pop_front() //删除第一个元素 21 q.push_front() //在list的头部添加一个元素 22 23 q.rbegin() //返回指向第一个元素的逆向迭代器 24 q.remove() //从list删除元素 25 q.remove_if() //按指定条件删除元素 26 q.rend() //指向list末尾的逆向迭代器 27 q.resize() //改变list的大小 28 q.reverse() //把list的元素倒转 29 q.size() //返回list中的元素个数 30 q.sort() //给list排序 31 q.splice() //合并两个list 32 q.swap() //交换两个list 33 q.unique() //删除list中重复的元素
七、Pair(对)
- 就是合成两个数据,这个用结构体模拟也行,但是直接使用Pair会方便很多
- 基本操作如下:
1 pair<int,int>q; //创建一个空对 2 pair<int,int>p(2,3);//创建一个对p,并分别赋值2,3 3 pair<int,int>s(p); //创建一个对s,拷贝p给s 4 5 //赋值利用make_pair函数 6 q = make_pair(1,2); 7 //访问pair内元素操作 8 q.first; //返回成员第一个数据 9 q.second; //返回成员第二个数据
八、Set(集合)
- 首先Set遵循数学集合三特性,无重复、无序性、确定性。我就不解释了。
- Set中内置红黑树进行排序,所以插入删除效率很高。
- 常用操作如下:
1 int a[] = {1,2,3,4,5}; 2 set<int>q; 3 set<int>p; 4 5 q.insert(x); //集合中插入元素 6 q.insert(a,a+5); //插入数组a至a+5的元素 7 q.find(x); //返回x值位置的迭代器,找不到返回q.end() 8 q.erase(iter); //删除集合中的元素 9 q.size(); //返回当前set容器中的元素个数 10 q.count(); //返回某个值元素的个数(根据set的特性,就是判断这个元素在不在,返回0或1) 11 q.begin(); //返回头位置迭代器 12 q.end(); //返回尾位置迭代器 13 q.rbegin(); //返回尾部反向迭代器 14 q.rend(); //返回头部反向迭代器 15 q.clear(); //删除set容器中的所有的元素 16 q.empty(); //判断set容器是否为空 17 q.lower_bound(); //返回指向大于(或等于)某值的第一个元素的迭代器 18 q.upper_bound(); //返回大于某个值元素的迭代器
- 当然,你也可以自定义Set内部的排序操作,例如:
1 struct cmp{ 2 bool operator() (const node &a,const node &b){ 3 return a.x < b.x; 4 } 5 }; 6 7 set<node,cmp>q;
九、Map
- 不知道该翻译成啥,干脆不翻译了 =7=
- map是一种关联容器,例如map<int,int>,第一个元素可以称为关键字,类似数组的下标,不会重复出现,而第二个元素为关键字的值,类似数组中存的元素,可以重复。
- map不能直接修改关键字,只能通过修改关键字的值间接修改关键字。
- 和Set一样,map也是内置红黑树对关键字进行排序。能够实现快速查找和删除功能。
- 基本操作:
1 map<int,int>q; 2 3 q.insert(pair<int,int>(1,2)); //通过pair进行插入操作 4 q.insert(map<int,int>::value_type (1,2));//通过value_type进行插入 5 q[1] = 2; //用数组方式进行插入 6 /*三者不同的是,当map存在这个关键字时 7 *数组方式会覆盖关键字的值,而insert操作无法插入。 8 */ 9 10 q.size(); //返回容器内元素个数 11 q.empty(); //判断容器是否为空 12 q.begin(); //返回头位置迭代器 13 q.end(); //返回尾位置迭代器 14 q.rbegin(); //返回尾部反向迭代器 15 q.rend(); //返回头部反向迭代器 16 q.find(key); //查找并返回关键字key的位置 17 q.count(key); //查询是否有关键字key(有则返回1,否则0) 18 q.lower_bound();//返回键值>=给定元素的第一个位置 19 q.upper_bound();//返回键值>给定元素的第一个位置 20 q.erase(iter); //删除迭代器iter的元素 21 q.erase(iter1,iter2);//删除[iter1,iter2)区间内的元素 22 q.erase(key); //删除关键字为key的元素 23 q.clear(); //清空容器 24 q.swap(p); //交换两个map 25 q.key_comp(); //返回比较元素key的函数 26 q.max_size(); //返回可以容纳的最大元素个数 27 q.value_comp(); //返回比较元素value的函数 28 q.equal_range();//返回特殊条目的迭代器对
- 当然你可以自己写内部排序函数
- 例如结构体中重载<号,或者编写仿函数,例如:
1 class sort{ 2 3 public: 4 bool operator() (node const &a,node const &b) const{ 5 return a.x < b.x; 6 } 7 8 };
十、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++的标准容器,但是我觉得性质差不多,就一起讲了,但是防止误导初学者,这里还是提一下。