1、list容器简介
- 链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。
- 链表由一系列结点(链表中每一个元素称为一个结点)组成,结点可以在运行时动态生成。
- 每个结点包括两部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域。
- 相较于vector的连续线性空间,list的好处是每次插入或者删除一个元素,就配置或者释放一个元素的空间。list对空间的运用绝对精准,不浪费。
- 对于任何位置的元素插入或删除,list永远是常数时间。
- 采用动态存储分配,不会造成内存浪费和溢出,链表的插入和删除只需要修改指针,不需要移动大量元素,但是空间和时间的额外耗费较大(这里理解为相较于vector容器,每一个节点需要额外空间存放指针域,另外每插入/删除一个元素都需要申请/释放一次空间,因此空间上和时间上的消耗相对较大)。
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/8b2a4cfb98288424715534dc63017256.png#pic_center)
2、list迭代器
- list容器不能像vector一样以普通指针作为迭代器,因为其结点不能保证在同一块连续的内存空间上。list迭代器必须有能力指向list的结点,并有能力进行正确的递增(指向下一个结点)、递减(指向上一个结点)、取值(取结点的数据值)、成员存取(结点的成员)操作。
- 由于list是双向链表,迭代器必须具备前移、后移的能力,所以list容器提供的是双向迭代器(Bidirectional Iterator).
- list插入和删除操作都不会造成原有list迭代器失效。这在vector是不成立的,因为vector插入操作可能造成空间重新配置,导致原有迭代器失效。list元素的删除,只有被删除的那个元素的迭代器失效,其他迭代器不受影响。
3、API
list<T> lstT;
list(beg,end);
list(n,elem);
list(const list& lst);
push_back(elem);
pop_back();
push_front(elem);
pop_front();
insert(pos,elem);
insert(pos,n,elem);
insert(pos,beg,end);
clear();
erase(beg,end);
erase(pos);
remove(elem);
empty();
size();
resize(num);
resize(num,elem);
assign(beg,end);
assign(n,elem);
list& operator=(cosnt list& lst);
swap(lst);
front();
back();
reverse();
sort();
- 系统提供的sort算法仅支持随机访问迭代器,其格式为sort(beg,end),因此list提供了自己的sort算法。
- 只有随机访问迭代器才支持+n的操作,因此对于list容器的双向迭代器不支持+n操作。而对于++操作随机访问迭代器和双向迭代器都支持。
- list容器存放自定义数据,如果删除某个节点,必须重载= =运算符。(remove函数的实现需要用到==)
#include<iostream>
#include<list>
#include<vector>
#include<algorithm>
using namespace std;
class Person{
public:
Person(string name,int age){
this->name=name;
this->age=age;
}
bool operator==(const Person& ob){
if(this->name==ob.name&&this->age==ob.age)return true;
return false;
}
bool operator<(const Person& ob){
return this->age<ob.age;
}
};
bool myComparePerson(const Person& ob1,const Person& ob2){
return ob1.age<ob2.age;
}
void printListPerson(list<Person>& L){
for(list<Person>::iterator it=L.begin();it!=L.end();it++){
cout<<(*it).name<<" "<<(*it).age<<endl;
}
}
void printListPerson(vector<Person>& v){
for(vector<Person>::iterator it=L.begin();it!=L.end();it++){
cout<<(*it).name<<" "<<(*it).age<<endl;
}
}
class Compare{
public:
bool operator()(const Person& ob,const Person& ob2){
return ob.age<ob2.age;
}
};
void test()
{
list<Person> L;
L.push_back(Person("小明",18));
L.push_back(Person("小红",15));
L.push_back(Person("小李",19));
L.push_back(Person("小王",14));
printListPerson(L);
Person temp("小明",18);
L.remove(temp);
printListPerson(L);
L.sort();
printListPerson(L);
L.sort(myComparePerson);
printListPerson(L);
vector<Person> v;
v.push_back(Person("小明",18));
v.push_back(Person("小红",15));
v.push_back(Person("小李",19));
v.push_back(Person("小王",14));
sort(v.begin(),v.end());
printListPerson(v);
sort(v.begin(),v.end(),myComparePerson);
printListPerson(v);
sort(v.begin(),v.end(),Compare());
}