一、综述
<vector>:可变大小数组。支持快速随机访问。在尾部之外的位置插入或删除元素可能很慢。
<deque>:双端队列。支持快速随机访问。在头尾位置插入/删除速度很快。
<list>:双向链表。只支持双向顺序访问。在list中任何位置进行插入/删除操作速度都很快。
<forward_list>:单向链表。只支持单向顺序访问。在链表任何位置进行插入/删除操作速度都很快。
<array>:固定大小数组。支持快速随机访问。不能添加或删除元素。
<string>:与vector相似的容器,但专门用于保存字符。随机访问快。在尾部插入/删除速度快。
通常用vector是最好的选择。其次list。
二、迭代器
- begin指向首元素,end指向尾元素之后。
- begin == end,vector为空
- begin != end,至少有一个元素
- 类型是iterator
- cbegin和cend的类型是const_iterator(不需要做写访问时 )
- rbegin和rend的类型是reverse_iterator
- 还有crbegin => const_reverse_iterator
- 定义一个迭代器
vector<int>::iterator iter;
三、容器的定义和初始化
- vector<int> vec1(vec2);
vector<int>vec1 = vec2; 【将vec1初始化为vec2的拷贝
- vector<string> svec{"a", "b", "c"};
- vector<string> svec={"a", "b", "c"}; 【将vec初始化为列表中的元素拷贝
- vector<int> vec1(b, e); 【初始化为迭代器b, e(直到但不包括)之中的元素拷贝
- vector<int> seq(n); 【seq包含n个元素
- vector<int> seq(n, t); 【seq包含n个值为t的元素
特殊:定义array
array<int, 42>; 【要指定大小,包含42个int的数组
四、赋值与swap
- array<int, 10> = {0}; 【全置为0
- array<int, 10> = {0,1,2,3,4,5,6,7,8,9}; 【列表赋值
- swap(c1, c2);
c1.swap(c2); 【交换c1与c2,比拷贝快,
- 只要类型一样就可以,连同size完全交换
- 迭代器、指针、引用还是在原来的容器上,不会跟着交换
特别的:对于顺序容器,assign
vectorString.assign(listChar.begin(), listChar.end()); 【将一个char型的list拷贝到string型的vector里
五、顺序容器的操作
- 添加元素(非array,因为array固定大小,forward_list比较特殊)
- c.push_back(t); 【在c的尾部添加一个值为t或者由args创建的元素。return void
c.emplace_back(args); 【forward_list不支持push_back
- c.push_front(t); 【vector和string不支持push_front,但是可以用insert插入到c.begin()之前
c.emplace_front(args); 【在c的头部添加一个值为t或者由args创建的元素。return void
- c.insert(p, t);
c.emplace(p, args); 【在迭代器p指向的元素之前插入一个值为t或者由args创建的元素。返回新添加元素的迭代器。
- c.insert(p, n, t); 【在迭代器p指向的元素之前插入n个值为t的元素。返回新添加的第一个元素的迭代器,若n=0,则返回p
c.insert(p, b, e); 【将迭代器b和e指定的范围内的元素插入到迭代器p之前
c.insert(p, il); 【il是一个花括号包围的元素值列表,将这些定值插入到迭代器p之前
特别的:使用insert的返回值,可以在一个特定的位置反复插入一个值。
while(cin>>word)
iter = lst.insert(iter, word);
- 访问元素
- c.back(); 【返回尾元素的引用
c.front(); 【返回收元素的引用
- c[n]; 【也可以直接用下标。适用于string, vector, deque, array
c.at(n); 【好像和上面差不多,但如果越界会抛出out_of_range异常
- 删除元素
- c.pop_back(); 【删除c的尾元素,返回void。forward_list不支持
c.pop_front(); 【删除c的首元素,返回void。vector和string不支持
- c.erase(p); 【删除迭代器p指向的元素,返回被删元素之后的迭代器
c.erase(b, e); 【删除迭代器b, e中间的元素,返回e后的迭代器
- c.clear(); 【清空c,返回void
- 改变容器大小
- c.resize(n); 【如果n比原本的size要大,多出来的值初始化;要小就直接删除
- c.resize(n, t); 【新添加的元素用t来初始化
另外:在对改变了容器的大小以后,迭代器、指针、引用可能会失效。所以应保证每次改变容器的操作之后都正确地重新定位迭代器。且,不要保存end返回的迭代器。
六、关于vector与string
- vector的增长方式是由系统分配比需求空间更大的内存空间当作备用。
- c.shrink_to_fit(); 【将capacity()减少为与size()相同大小(只是请求,并不保证退还内存。只适用于vector、string、deque
- c.capacity(); 【不重新分配空间的话,c可以保存多少元素 只适用于vector、string
- c.reserve(n); 【通知容器它应该准备保存多少元素。如果需求大于当前空间,则分配一样或更大的空间;如果小,就什么也不做。
- 构造string的其他方法:
- string s(cp, n); 【cp是char型指针,s是cp指向的前n个字符的拷贝
- string s(s2, pos2); 【s是s2从下标pos2开始的字符的拷贝
- string s(s2, pos2, len2); 【s是s2从下标pos2开始的len2个字符的拷贝
- substr:(相当于python的切片
- s.substr(pos, n); 【从pos开始的n个字符的拷贝,n默认为是从pos到末尾
- string的其他操作
- insert、erase可以接受下标的版本
- insert、assign可以接受char字符数组
- s.append(args); 【在末尾添加
- s.replace(pos, n, args); 【在pos后删除n个字符,用args替换,args的长度可以大于n
- string的搜索(返回指定字符的下标,没有返回npos
- s.find(args); 【在s中精确查找args第一次出现的位置
- s.rfind(args); 【在s中精确查找args最后一次出现的位置
- s.find_first_of(args); 【在s里查找第一次出现args里字符的位置
- s.find_last_of(args); 【在s里查找最后一次出现args里字符的位置
- s.find_first_not_of(args); 【在s里查找第一次没出现args里字符的位置
- s.find_last_not_of(args); 【在s里查找最后一次没出现args里字符的位置
args的形式:
c, pos |
pos开始查找字符c, pos默认0 |
s2, pos |
pos开始查找字符串s2 |
cp, pos |
pos开始查找cp指向的C风格字符串 |
cp, pos, n |
pos开始查找cp指向的数组前n个字符 |
循环查找s中所有出现numbers的位置:
while( (pos = s.find_first_of(numbers, pos) ) != string::npos){
process();
++pos;
}
- compare函数:(s.compare(args);
参数形式:
s2 |
比较s与s2 |
pos1, n1, s2 |
将s中pos2开始的n1个字符与s2比较 |
pos1, n1, s2, pos2, n2 |
将s中pos1开始的n1个字符与s2中pos2开始的n2个字符比较 |
cp |
比较s与cp指向的直到空字符 |
pos1, n1, cp |
s中从pos1开始的n1个字符与cp指向直到空字符的比较 |
pos1, n1, cp, n2 |
s中从pos1开始的n1个字符与cp指向的n2个字符的比较 |
- 数值转换
to_string(val); |
val可以是任意算数形式 |
stoi(s, p, b); stol(s, p, b); stoul(s, p, b); stoll(s, p, b); stoull(s, p, b); |
都是string转换为整型,unsigned、long。 p是size_t型指针,用来保存第一个非数值型字符的下标。 默认0,即不保存。 b是转换用的基数,默认10。 |
stof(s, p); stod(s, p); stold(s, p); |
string 转换为float和double,p同上(但是不知道怎么用== |
七、容器适配器
三个顺序容器适配器:stack、queue、priority_queue
- 默认情况下,stack和queue是基于deque实现的,priority_queue是基于vector;
- 但是因为stack只需push_back等,所以除了array、forward_list都可以建造;
- queue需要push_front等,所以不能用vector;
- priority_queue需要随机访问,所以能构造与vector、deque,不可list。
- stack适配器
s.pop(); |
pop栈顶,但不返回该元素值 |
s.push(item); s.emplace(); |
将item压入栈顶,或者由args建造 |
s.top(); |
仅仅返回栈顶元素 |
用deque等构建了stack以后,就不能用deque的操作了,要用stack自己的操作
- deque适配器(同priority_queue
q.pop(); |
返回队列首元素,或priority_queue最高优先级元素,但不删除 |
q.front(); |
返回首元素或尾元素,但不删除 |
q.back(); |
只适用于queue |
q.top(); |
返回最高优先级元素,只适用于priority_queue |
q.push(item); q.emplace(args); |
在queue的末尾或priority_queue中恰当位置创建一个元素, 值为item或由args创建 |
priority_queue允许给元素建立优先级