参考了http://www.cplusplus.com,对网站上的内容有所精简,例程是自己给出的。
这些容器有许多相似的地方,比如迭代器begin()都是指向第一个元素,end()指向最后一个元素的下一个位置,涉及到区间时都是半开半闭(左闭右开或者左开右闭)。又比如初始化时一般都有以下方式(这里以list为例):
/******各种初始化******/
list<int> ex1;// 默认初始化为一个空链表
list<int> ex2(10);// 创建一个含有10个默认值是0的列表
list<int> ex3(10,2);// 创建一个含有10个默认值是2的列表
list<int> ex4(ex3);// 用ex3初始化ex4
list<int> ex5(ex4.begin(),ex4.end());// 使用区间元素初始化
list<int> ex6={1,2,3,4,5,6};//使用列表初始化
这些相同的地方接下来就不一一讨论了。
1、list
(1)简介
C++中的list是一个双向链表(doubly-linked list)。它的插入和删除均为常数时间O(1),但是不支持对元素的直接访问(即使用[]来访问元素),同时使用list也需要额外的内存开销。
(2)常用操作
a、迭代器
/******迭代器******/
list<int>:: iterator iter1,iter2; // 申明(正向)迭代器
list<int>:: reverse_iterator iter3,iter4;// 申明反向迭代器
iter1=ex6.begin();// 指向第一个元素
iter2=ex6.end();// 指向最后一个元素的下一个位置
iter3=ex6.rbegin();// 指向最后一个元素
iter4=ex6.rend();// 指向第一个元素的前一个位置
//cout<<*(iter1+1)<<endl;// 错误!这是一个链表,只能顺序访问!但是list的迭代器可以++和--
需要注意的地方是list只能顺序访问,所以对迭代器进行加减是不允许的。
此外还有cbegin(),cend(),crbegin(),crend(),这和const关键字有关,这里不展开。
b、容量
empty()函数测试list是不是空的;
size()函数返回大小;
max_size()返回list所能存储的最大大小,所有的list都会返回一个相同的值,很大很大(768614336404564650)。
c、元素访问
/******元素访问******/
cout<<ex6.front()<<endl;// 用front()函数访问第一个元素
cout<<ex6.back()<<endl;// 用back()函数访问最后一个元素
d、修改
/******修改******/
ex6.assign(2,7);// assign的作用是重新赋值,例如这行代码给ex6赋值2个7
ex6.assign(ex3.begin(),ex3.end());// 给ex6赋值这个范围的元素
ex6.emplace_front(1);// 在最前面插入1
ex6.emplace_back(3);// 在最后面插入3
ex6.emplace(ex6.begin(),0);// 第一个参数是迭代器,是插入的位置,后面是插入的数据,例如这里插入了0
ex6.emplace(ex6.end(),9);// 在最后插入9
ex6.push_back(233);// 往末尾push一个元素
ex6.pop_back();// pop末尾元素
ex6.push_front(222);// 往前面push一个元素
ex6.pop_front(); // pop前面元素
list<int>:: iterator it=ex6.begin();
it++;// ex6中的元素是0 1 2 2 2 2 2 2 2 2 2 2 3 9, it指向1
ex6.insert(it,10);// 10插到了1前面,it仍然指向1
ex6.insert(it,2,9);// 在1前面插入两个9
list<int> ex7={-1,-1};
ex6.insert(it,ex7.begin(),ex7.end());// 用迭代器来插入,只要是迭代器都可以,例如可以用vector
list<int> ex8={10,20,30,40,50,60,70,80,90};
list<int>:: iterator it1,it2;
it1=it2=ex8.begin();// 10,20,30,40,50,60,70,80,90
// ^^
advance(it2,7);// 10,20,30,40,50,60,70,80,90
// ^ ^
ex8.erase(it2);// 10,20,30,40,50,60,70,90
// ^ ^
it1++;
it2--;// 10,20,30,40,50,60,70,,90
// ^ ^
ex8.erase(it1,it2);// 10,70,90
// ^^
ex6.swap(ex8);// 交换两个链表的内容
ex6.resize(5);// 改变容器大小,ex6的内容是10,70,90,现在变成10,70,90,0,0
ex6.resize(7,2);// 现在变成10,70,90,0,0,2,2
ex6.resize(0);// 现在什么都没了,若调用size()函数会得到0
ex6.clear();// 将ex6的内容全清空
e、其他
#include<iostream>
#include<list>
using namespace std;
bool predicate1(const int& val){return (val>=30);}
bool predicate2(const int& val1,const int& val2){return abs(val1-val2)<=1;}
bool cmp(double val1,double val2){/*do something here...*/}
int main(int argc, char* argv[])
{
list<int> mylist1={1,2,3,4,5};
list<int> mylist2={10,20,30};
list<int>::iterator it=mylist1.begin();
mylist1.splice(it,mylist2);// 第一个参数是插入位置,第二个参数是插过来的list
// mylist1变成10,20,30,1,2,3,4,5
// mylist2变为空
mylist2.splice(mylist2.begin(),mylist1,it);// 还可以有第三个参数,指向要插入的元素
// mylist2变成1
// 指向1的迭代器it失效了!不能再用!
mylist