主要分为序列式、关联式和无序式。
- 序列式包括array、vector(后面可扩充)、deque(前后可扩充)、双向链表list、单向链表forward-list。
- 关联式底层为树结构,是基于key-value结构的,主要有Set/MultiSet和Map/MultiMap。对于set,key和value是不分的。set和map的key都不可以重复,但如果使用MultiSet和MultiMap,则可以重复。
- 无序式也是基于key-value。
迭代器
迭代器提供了遍历容器的方法
容器 | 访问方式 |
---|---|
vector | 随机访问 |
deque | 随机访问 |
list | 双向 |
set/multiset | 双向 |
multimap | 双向 |
stack | 不支持 |
queue | 不支持 |
priority_queue | 不支持 |
迭代器类对容器中元素的访问方式:指针
迭代器访问元素移动时,源码对运算符进行了重载
迭代器失效问题
1. vector 向量
vector可以看作是一个动态数组,长度可以动态变化。在尾部添加删除元素效率高,中间添加删除效率低。
vector带参构造
vector(vector1.begin(), vector1.end());
vector(n, elem);
vector(const vector & c);
vector 赋值
vetor.assign(vector.begin(), vector.end());
vetor.assign(n, elem);
vector & operator=(const vector &vec); //重载等号操作符
vector.swap(vector); 元素互换
vector.size(); 元素个数
vector.empty(); 判断是否为空
vector.resize(num); 重新指定容器长度为num,若容器变长,用默认值填充,若变短,超出的元素被删除
vector.resize(num, elem); 重新指定容器长度为num,若容器变长,用elem填充,若变短,超出的元素被删除
vector尾部添加删除
vector.push_back(num);
vector.emplace_back(num); 优先使用
vector.pop_back();
push_back的底层在添加前先创建元素,然后拷贝到vector中,emplace_back则直接添加省去拷贝过程
vector数据存取
vector.at(index); 越界报out_of_range错误
vector[index]; 越界会运行出错
vector.front();
vector.back();
vector.insert(position, ele); 某位置插入数据
vetor.insert(position, n, elem); 某位置插入n个elem
vector.insert(position, vector.begin(), vector.end()); 在某位置插入一段数据
vector删除
vector.clear(); 删除所有数据
vector.erase(vector.begin(), vector.end()); 删除某一段数据,返回下一个元素位置
vector.erase(position); 删除某位置元素,返回下一个数据位置
2. list 双向链表
list不可以随机存取数据,不支持at()和[]方法,可以用迭代器++遍历,但不可以+5这样遍历
list方法
list.push_back(elem); 尾部添加元素
list.pop_back(); 删除最后一个元素
list.push_front(elem); 开头插入元素
list.pop_front(); 开头移除元素
数据读取
list.front(); 返回第一个元素
list.end(); 返回倒数最后一个元素,也就是第一个
list的带参构造、赋值、判断大小、插入删除和vector差不多
list逆序排列
list.reverse()
list.begin();
list.end();
list.rbegin();
list.rend();
3. deque
deque是双端数组,可以在头部尾部进行操作
在头部尾部操作迅速,在中间插入删除比较麻烦
deque.push_front(elem); 在容器头部插入一个数据
deque.pop_front(); 删除第一个数据
4. stack 栈
stack是先进后出
stack.push(elem); 在栈顶添加元素
stack.pop(); 在栈顶移除元素
stack.top(); 读取栈顶元素
stack拷贝与赋值
stack(const stack &s);
stack & operator=(const satck & s);
5. queue 队列
queue 先进先出
queue.push(elem); 队尾添加元素
queue.pop(); 队头移除第一个元素
queue.back(); 返回最后一个元素
queue.front(); 返回第一个元素
6. set 集合
set中键值唯一,并且按照一定顺序排列。set不可以直接存取元素(at()和[]不行)
multiset键值不唯一
不可以直接修改set和multiset中的元素值,若修改会先删除再插入
set.insert(elem);
set.begin();
set.end();
set.rbegin(); 返回倒数第一个元素的迭代器
set.rend(); 返回倒数最后一个元素迭代器,也就是第一个
接下来涉及到了functor的使用,在这使用functor可以定制排序的规则
先看set中如何使用的
set<int, less<int>> setA;
set<int, greater<int>> setA;
less,greater在这代表了按照升序还是降序排列元素,为什么可以这样?
functor是函数对象,其实就是把一个类当作函数来调用,是重载了操作符的普通类对象。而less和greater就是函数对象
class greater{
bool operator()(const int & left, const int & right)
{
return (left > right);
}
}
而容器就是调用operator去比较两个值的大小。
set的查找
set.find(elem); 返回elem元素对应的迭代器
set.count(elem); 返回值为elem的元素个数,对set来说为1或0,multiset可能大于1
set.lower_bound(elem); 返回第一个>= elem元素的迭代器
set.upper_bound(elem); 返回第一个 >elem 元素的迭代器
7. map 映射
map存储的是键值对
map中key值唯一,且有序。插入删除操作比vector快。可以直接修改key对应的value。
multimap可以出现重复的key,但不支持[]操作。
插入元素三种方式
map.insert(pair(3, "11"));
map.insert(map<int, string>::value_type(1, "111"));
map[1] = "11";
第三种会先去查找是否存在此key,没有再插入,有则修改
map[];
map<int, string>::iterator it = map.find(elem); 失败返回end()的返回值
map.at(); key不存在 out_of_range异常