6. List容器
6.1 基本概念
链表(list)是一种物理存储单元上非连续的存储结构,数据元素的逻辑顺序是通过链表中的指针链接实现的
功能:将数据进行链式存储
链表的组成:由一系列的结点构成
结点的组成:一个存储数据元素的数据域,另一个是存储下一个结点地址的指针域
STL中的链表是一个双向循环链表
由于链表的存储方式并不是连续的内存空间,因此链表中的迭代器支持前移和后移,属于双向迭代器。
优点:
- 采用动态存储分配,不会造成内存浪费和溢出
- 链表执行插入和删除操作十分方便,修改指针即可,不需要移动大量元素
缺点:空间(指针域)和时间(遍历)额外耗费较大
插入操作和删除操作都不会导致原有list迭代器的失效,在vector中是不成立的
6.2 构造函数
函数原型:
list v; // 采用模板实现类实现,默认构造函数
list(begin,end); // 将[beg,end]区间中元素拷贝给本身
list(n,elem); // 构造函数将n个elem拷贝给本身
list(const list &lst); // 拷贝构造函数
6.3 赋值和交换
函数原型:
list& operator=(const list &lst); // 重载等号操作
assign( beg, end ); // 将[begin,end]区间中元素赋值给本身
assign( n, elem ); // 将n个elem拷贝赋值给本身
swap(lst); // 将lst与本身交换
6.4 大小操作
函数原型:
empty(); // 判断容器是否为空
size(); // 返回容器中元素个数
resize(int num); // 重新制定容器的长度为num,若容器变长,则以默认值填充新位置;
resize(int num,elem); // 重新制定容器的长度为num,若容器变长,则以elem值填充新位置;
// 若容器变短,则末尾超出容器长度元素被删除
6.5 插入和删除
两端插入操作:
push_back(ele); // 尾部插入元素ele
push_front(ele); // 头部插入元素ele
pop_back(); // 删除最后一个元素
pop_front(); // 删除第一个元素
指定位置操作:
insert(const_iterator pos,ele); // 在pos插入一个ele元素的拷贝,返回新数据的位置
insert(const_iterator pos,int n,ele); // 在pos插入n个ele元素的拷贝,返回新数据的位置
insert(const_iterator pos,begin,end); // 在pos位置插入[begin,end]区间数据,无返回值
erase(const_iterator pos); // 删除pos位置数据,返回下一个数据位置
erase(const_iterator start,const_iterator end); // 删除[begin,end]区间数据,返回下一个数据位置
clear(); // 删除容器中所有元素
remove(elem); // 删除容器中所有与elem值匹配的元素
6.6 数据存储
back(); // 返回最后一个元素
front(); // 返回第一个元素
list不支持使用[]和at方式访问容器中的元素,原因是list本质是链表,不适用连续线性空间存储数据,迭代器也是不支持随机访问的
6.7 反转和排序
将容器中的元素反转,以及将容器中的数据进行排序
reverse(); // 反转链表
sort(); // 链表排序
所有不支持随机访问迭代器的容器,不可以用标准算法;不支持随机访问迭代器的容器,内部会提供对应的一些算法。
// 降序
bool myCompare(int v1,int v2)
{
return v1 > v2;
}
list<int>L;
L.sort(myCompare);
对于自定义数据类型,必须要指定排序规则,否则编译器不知道如何进行排序
高级排序只是在排序规则上再进行一次逻辑规则制定,并不复杂
7. Set容器
7.1 set基本概念
简 介: 所有元素都会在插入时自动被排序
本 质: set/multiset属于关联式容器,底层结构是用二叉树实现。
set和multiset区别:set不允许容器中有重复的元素;multiset允许容器中有重复的元素
7.2 set构造和赋值
set容器插入数据时用insert
set容器插入数据的数据会自动排序
函数原型:
set v; // 采用模板实现类实现,默认构造函数
set(const set &st); // 拷贝构造函数
set& operator=(const set &st); // 重载等号操作
7.3 set大小和交换
empty(); // 判断容器是否为空
size(); // 返回容器中元素个数
swap(st); // 将st与本身交换
7.4 set插入和删除
insert(elem); // 插入elem元素
clear(); // 删除容器中所有元素
erase(const_iterator pos); // 删除pos位置数据,返回下一个数据位置
erase(const_iterator start,const_iterator end); // 删除[begin,end]区间数据,返回下一个数据位置
erase(elem); // 删除容器中值为elem的元素
7.5 set查找和统计
find(key); // 查找key是否存在,若存在,返回该键的元素的迭代器;若不存在,返回set.end()
count(key); // 统计key的元素个数,对于set,结果为1或0
7.6 set和multiset区别
- set不可以插入重复数据,而multiset可以
- set插入数据的同时会返回插入结果,表示插入是否成功
- multiset不会检测数据,因此可以插入重复数据
7.7 pair对组创建
功能描述:
成对出现的数据,利用对组可以返回两个数据
两种创建方式:
pair p(value1,value2);
pair p = make_pair(value1,value2);
7.8 set排序
set容器默认排序规则为从小到大,利用仿函数,可以改变排序规则
class MyCompare
{
public:
bool operator()(int v1,int v2) const
{
return v1 > v2;
}
}
set<int,MyCompare> s;
8. Map容器
8.1 map基本概念
简 介:
- map中所有元素都是pair
- pair中第一个元素为key(键值),起到索引作用,第二个元素为value(实值)
- 所有元素都会根据元素的键值自动排序
本 质:
- map/multimap属于关联式容器,底层结构是用二叉树实现
优 点:
- 可以根据key值快速找到value
map和multimap区别:
- map不允许容器中有重复key元素
- multimap允许容器中有重复key值元素
8.2 map构造和赋值
函数原型:
map mp; // 默认构造函数
map(const map &mp); // 拷贝构造函数
赋值:
map& operator=(const map &mp); // 重载等号操作
// map中所有元素都是成对出现,插入数据时候要使用对组
8.3 map大小和交换
size(); // 返回容器中元素个数
empty(); // 判断容器是否为空
swap(map); // 交换两个集合容器
8.3 map插入和删除
insert(elem); // 插入elem元素
clear(); // 删除容器中所有元素
erase(const_iterator pos); // 删除pos位置数据,返回下一个元素的迭代器
erase(const_iterator beg,const_iterator end); // 删除[beg,end]区间数据,返回下一个元素迭代器
erase(key); // 删除容器中键值为key的元素
// insert 4种方法
map<int,int> m;
m.insert(pair<int,int>(1,10));
m.insert(make_pair(2,20));
m.insert(map<int,int>::value_type(3,30));
m[4] = 40; //不推荐用于插入,但可以用于key访问value
8.4 map查找和统计
find(key); // 查找key是否存在,若存在,返回该键的元素的迭代器;若不存在,返回map.end()
count(key); // 统计key的元素个数
8.5 map容器排序
利用仿函数,可以改变排序规则
// 排序
class MyCompare
{
public:
bool operator()(int v1,int v2) const
{
// 降序
return v1 > v2;
}
}
map<int,int,MyCompare> m;