【STL——list】
引入
list容器完成的功能实际上和数据结构中的双向链表是极其相似的,list中的数据元素是通过链表指针串连成逻辑意义上的线性表,也就是list也具有链表的主要优点,即:在链表的任一位置进行元素的插入、删除操作都是快速的。

与之前几篇流程相同,一切操作前先加头文件:
#include
初始化
list<int> l1; //创建一个空链表list<int> l2(22); //创建一个有22个空元素的链表list<int> l3(5, 33); //创建一个有5个元素且值均为33的链表list<int> l4(l3.begin(), l3.end()); //创建一个链表并以l3.begin()~l3.end()的元素内容进行初始化list<int> l5(l4); //创建一个与l4内容相同的链表(赋值)
注意,在之前几篇对于l4的初始化那里是写类似于这种:
list l4(l3.begin(), l3.begin()+3);
但对于list容器来说不能这样写,但可以用迭代器进行调整,实现(如果只取从begin开始往后的少许元素或取到end之前的元素)。
如:
- begin附近:
list<int> l3(5, 33); //创建一个有5个元素且值均为33的链表
list<int>::iterator it =l3.begin();
it++;
it++;
list<int> l4(l3.begin(), it); //创建一个链表并以l3.begin()~l3.begin()+2的元素内容进行初始化
- end附近:
list<int>::iterator it =l3.end();
it--;
it--;
list<int> l4(l3.begin(), it); //创建一个链表并以l3.begin()~l3.end()-2的元素内容进行初始化
迭代器遍历和之前几篇一样,除了不能直接begin()++
常用函数
empty()
返回一个bool类型的值,只存在真和假,当链表为空时为真,不为空时为假。

显然此时L5不为空,判断为假,输出0
size()

接上述初始化之后用接近end处且it–的代码部分,l3.end=5,两次减减之后变为3,则l4复制到就是l3的[0,3)部分的内容,复制了0、1、2这3个下标的元素。l5复制l4的内容,则l5也是3个元素,所以输出3.
push、pop
- 链表前
push_front()表示在链表最前端插入一个数据
pop_front()表示在链表最前端删除一个数据
list<int> l3(5, 33); //创建一个有5个元素且值均为33的链表
//现在l3={33,33,33,33,33}
l3.push_front(9); //在l3前面插入1个9
//现在l3={9,33,33,33,33,33}
cout << endl;
l3.pop_front(); //表头出队一个元素
//现在l3={33,33,33,33,33}
- 链表后
push_back()表示在链表尾插入一个数据
pop_back()表示将链表尾删除一个数据
list<int> l3(5, 33); //创建一个有5个元素且值均为33的链表//现在l3={33,33,33,33,33}l3.push_back(9); //在表尾插入1个9//现在l3={33,33,33,33,33,9}l3.pop_back(); //表尾出队1个元素//现在l3={33,33,33,33,33}
insert()
与push相比,insert可以插在任意位置,且可插入任意个元素。
语法部分省略直接看例子,用注释部分理解代码含义:
list<int> l3(5, 33); //创建一个有5个元素且值均为33的链表//现在l3={33,33,33,33,33}l3.push_back(9); //在表尾插入1个9//现在l3={33,33,33,33,33,9}l3.pop_back(); //表尾出队1个元素//现在l3={33,33,33,33,33}list<int>::iterator it = l3.begin();it++;it++; //it=2l3.insert(it, 45); //在2的位置上插入45//现在l3={33,33,45,33,33,33}list<int>::iterator it2 = l3.begin();it2++;it2++;l3.insert(it2, 2, 1);//在2的位置上插入2个1//现在l3={33,33,1,1,45,33,33,33}list<int>::iterator it3 = l3.begin();it3++;l3.insert(it3, l2.begin(), l2.end()); //在1的位置后面插入l2的[begin,end)//现在l3={33,6,6,6,33,1,1,45,33,33,33}
erase()
list<int> l2(3, 6);
list<int> l3 = { 33,33,1,1,45,33,33,33 };
list<int>::iterator it3 = l3.begin();
it3++;
l3.insert(it3, l2.begin(), l2.end()); //在1的位置后面插入l2的[begin,end)
//现在l3={33,6,6,6,33,1,1,45,33,33,33}
l3.erase(l3.begin()); //删除队头元素
//现在l3={6,6,6,33,1,1,45,33,33,33}
list<int>::iterator it4 = l3.end();
it4--;
l3.erase(l3.begin(),it4); //删除l3下标[begin,end-1)的元素
//现在l3={33}
sort()
list<int> l3 = { 6,6,6,33,1,1,45,33,33,33 };
l3.sort();
//现在l3={1,1,6,6,6,33,33,33,33,45}
reverse()
list<int> l3 = { 6,6,6,33,1,1,45,33,33,33 };l3.reverse(); //翻转//现在l3={33,33,33,45,1,1,33,6,6,6}
函数列表


练习
利用list将Person自定义数据类型进行排序,Person中属性有姓名、年龄、身高。
排序规则:按照年龄进行升序,如果年龄相同按照身高进行降序。
- person类
class person {
public:string name;int age;int height;
public:person(string name, int age, int height) {this->name = name;this->age = age;this->height = height;}
};
- 自定义比较方法
bool compare(person& p1, person& p2) {if (p1.age == p2.age) {
//如果p1.height > p2.height,就为真,不交换位置
// 若p1.height < p2.height,就为假,两者交换位置return p1.height > p2.height;}else {return p1.age < p2.age;}
}
- 调用
void test() {list<person> L;person p1("张三",20,180);person p2("李四", 20, 183);person p3("王五", 19, 190);person p4("李华", 19, 170);L.push_back(p1);L.push_back(p2); L.push_back(p3);L.push_back(p4);cout << "排序前:" << endl;for (auto it = L.begin(); it != L.end(); it++) {cout << "个人信息:"<<(*it).name << (*it).age <<' ' << (*it).height;}cout << endl;L.sort(compare); //使用自定义的比较函数cout << "排序后:" << endl;for (auto it = L.begin(); it != L.end(); it++) {cout << "个人信息:" << (*it).name << (*it).age << ' ' << (*it).height;}
}int main() {test();return 0;}