一、list的特点
由于链表的存储方式并不是连续的内存空间,因此链表list中的迭代器只支持前移和后移,属于双向迭代器
list的优点:
采用动态存储分配,不会造成内存浪费和溢出
链表执行插入和删除操作十分方便,修改指针即可,不需要移动大量元素
list的缺点:
链表灵活,但是空间(指针域)和时间(遍历)额外耗费较大
List有一个重要的性质,插入操作和删除操作都不会造成原有list迭代器的失效,这在vector是不成立的。
总结:STL中List和vector是两个最常被使用的容器,各有优缺点
能进行算数运算的迭代器只有随机访问迭代器。要求容器元素存储在连续空间内;
即vector、string、deque的迭代器是有加减法的;
但是list、forward_list、map、set的迭代器仅支持++iter、–iter这些操作。
二、list容器的构造
1、默认构造
2、拷贝构造
3、区间或部分构造
4、n个相同元素构造
list<int>nl;
nl.push_back(1); //尾插
nl.push_back(2);
nl.push_front(6); //前插
nl.push_front(7);
printlist(nl); //7 6 1 2
list<int>nl2(nl); //拷贝构造
list<int>nl3(nl2.begin(), nl2.end()); //区间拷贝
list<int>nl4(3, 10); //n个相同元素构造
printlist(nl4); //10 10 10
三、list容器的赋值与交换
1、assign选择性赋值
assign(迭代器开始,迭代器结束) 这里迭代器不能进行加减数值了
assign(n, data);
2、赋值符号“=”赋值
3、swap交换
nl4.swap(nl2); //交换nl4和nl2
nl4.assign(nl.begin(), nl.end()); //部分拷贝 链表迭代器不能进行加减了
printlist(nl4); //7 6 1 2
nl4 = nl3; //全拷贝
nl4.assign(3, 9); //n个相同值拷贝
printlist(nl4); //9 9 9
四、list容器的大小
1、容器大小size
2、容器是否为空empty
3、容器的重新确定大小 增加的空间默认值为0 resize(容量值,默认值=0)
cout <<"nl4容器大小:"<< nl4.size() << endl; //nl4容器大小:3
cout <<"nl4容器是否为空:"<< nl4.empty() << endl; //nl4容器是否为空:0
nl4.resize(5); //新增2个数据默认值为0
printlist(nl4); // 9 9 9 0 0
nl4.resize(7, 7); //新增2个数据默认值为7
printlist(nl4); //9 9 9 0 0 7 7
五、list容器的插入和删除
1、容器前后插入 push_front push_back
2、容器前后的删除 pop_front pop_back
3、插入值 insert(pos,elem) insert(pos,n,elem)insert(begin,end)
4、全部清除 clear()
5、删除位置或区间值erase(pos) erase(begin, end)
6、删除匹配值 remove(elem)
六、list容器的迭代器特点
能进行算数运算的迭代器只有随机访问迭代器。要求容器元素存储在连续空间内;
即vector、string、deque的迭代器是有加减法的;
但是list、forward_list、map、set的迭代器仅支持++iter、–iter这些操作。
如果要查找后面n个元素的位置可以通过下面代码进行
list<int>::iterator it = nl2.begin();
for (size_t i = 0; i < 2; i++)
{
++it;
}
list<int>nl3(it, nl2.end()); //区间拷贝第三个元素及以后元素
七、数据的存取
1、不是连续存储空间,不能用at [] assign等进行存取
2、读list前面用front,从尾部读用back
3、用迭代器读取 *it
list<Person> lp;
Person p1("刘备",35 ,175);
Person p2("曹操",45 ,180);
Person p3("孙权",40,170);
lp.push_back(p1);
lp.push_back(p2);
lp.push_back(p3);
for (list<Person>::iterator it=lp.begin();it!=lp.end();it++)
{
cout << "姓名:" << (*it).name << " 年龄:" << (*it).age << " 身高:" << (*it).height << endl;
}
cout << " 第一个数据:" << lp.front().name << " " << lp.front().age << " " << lp.front().height << endl;
cout << "最后一个数据:" << lp.back().name << " " << lp.back().age << " " << lp.back().height << endl;
八、list排序和反转
1、随机访问容器可以利用algorithm提供的排序函数,list不属于这个类别应使用list内部提供的sort函数排序。
2、sort函数只提供内置类型的升序排序
3、可以重新仿函数进行多种类型多种方式的排序
4、反转revert
void printlist(list<Person>& lp) {
for (list<Person>::iterator it = lp.begin(); it != lp.end(); it++)
{
cout << "姓名:" << (*it).name << " 年龄:" << (*it).age << " 身高:" << (*it).height << endl;
}
}
bool listcompare(Person p1, Person p2) {
if (p1.age == p2.age) {
return p1.height > p2.height;
}
else {
return p1.age < p2.age;
}
}
void test() {
list<Person> lp;
Person p1("刘备", 35, 175);
Person p2("曹操", 45, 180);
Person p3("孙权", 40, 170);
Person p4("赵云", 25, 190);
Person p5("张飞", 35, 160);
Person p6("关羽", 35, 200);
lp.push_back(p1);
lp.push_back(p2);
lp.push_back(p3);
lp.push_back(p4);
lp.push_back(p5);
lp.push_back(p6);
printlist(lp);
cout << "--------" << endl;
lp.sort(listcompare);
printlist(lp); //按照年龄升序,年龄相同按照身高
cout << "--------" << endl;
lp.reverse(); //反转原来的数据
printlist(lp);
}