目录
功能:将数据进行链式存储
-
链表(list):是一种物理存储单位上非连续的存储结构,数据元素的逻辑顺序是通过链表中的指针链接实现的
-
链表的组成:链表有一系列结点组成
-
结点的组成:两个部分,一部分是存储数据元素的数据域,另一部分是存储下一个地址的指针域
-
链表的优点:可以对任意位置进行快速插入和删除的操作
-
链表的缺点:遍历速度慢(比数组),占用空间大(比数组)
-
STL中的链表是一个双向循环链表
由于链表的存储方式并不是连续的内存空间,因此链表 list 中的迭代器只支持前移和后移,属于双向迭代器
-
list 优点:
- 采用动态存储分配,不会造成内存浪费和溢出(vector 容器的容量在创建空间很大时会不等于容器大小,这就是一定的空间浪费)
- 链表执行插入和删除效率高
-
list 缺点:
- 链表灵活,但是空间(指针域)和时间(遍历)额外消耗大
-
list 有一个重要的性质,插入操作和删除操作都不会造成原有 list 迭代器的失效,这在 vector 是不成立的(重新分配新空间,将旧数据放到新空间,迭代器也就失效了)
-
在 STL 中 list 和 vector 是很常用的容器
功能:
- 创建 list 容器
函数原型:
// list采用模板类实现 listlst; // 构造函数将 [beg, end) 区间中的元素拷贝给本身 list(beg, end); // 构造函数将 n 个 elem 拷贝给本身 list(n, elem); 拷贝构造函数 list(const list& lst);
测试代码:
- #include
- using namespace std;
- #include
-
- void PrintList(const list<int>& L) {
- for (list<int>::const_iterator Lit = L.begin(); Lit != L.end(); ++Lit) {
- cout << *Lit << " ";
- }
- cout << endl;
- }
-
- void test() {
- // 创建 list 容器
- list<int>L1;
-
- // 添加数据
- L1.push_back(10);
- L1.push_back(20);
- L1.push_back(30);
- L1.push_back(40);
-
- PrintList(L1); // 10 20 30 40
-
- // 区间的方式构造
- list<int>L2(L1.begin(), L1.end()); // 双向迭代器只能 ++、--
- PrintList(L2); // 10 20 30 40
-
- // n 个 elem
- list<int>L3(5, 10);
- PrintList(L3); // 10 10 10 10 10
-
- }
-
- int main() {
- test();
- system("pause");
- return 0;
- }
运行结果:

功能:
- 给 list 容器进行赋值,以及交换 list 容器
函数原型:
// 将 [beg, end) 区间中的数据拷贝赋值给本身 assign(beg, end); // 将 n 个 elem 拷贝赋值给本身 assign(n, elem); // 重载 = 操作符 list& operator=(const list& lst); // 将 lst 与本身的元素互换 swap(lst);
测试代码:
- #include
- using namespace std;
- #include
-
- void PrintList(const list<int>& L) {
- for (list<int>::const_iterator Lit = L.begin(); Lit != L.end(); ++Lit) {
- cout << *Lit << " ";
- }
- cout << endl;
- }
-
- void test() {
- list<int>L1;
- L1.push_back(10);
- L1.push_back(20);
- L1.push_back(30);
- L1.push_back(40);
-
- list<int>L2;
- // 将 [beg, end) 区间中的数据拷贝赋值给本身
- L2.assign(++L1.begin(), --L1.end()); // 双向迭代器,前置++--才有用
- PrintList(L2); // 20 30
-
- list<int>L3;
- // 重载 = 操作
- L3 = L1;
- PrintList(L3); // 10 20 30 40
-
- list<int>L4;
- // n 个 elem 赋值
- L4.assign(4, 10);
- PrintList(L4); // 10 10 10 10
-
- // swap 交换
- L4.swap(L3);
- PrintList(L3); // 10 10 10 10
- PrintList(L4); // 10 20 30 40
- }
-
- int main() {
- test();
- system("pause");
- return 0;
- }
运行结果:

功能:
- 对 list 容器的大小进行操作
函数原型:
// 返回容器中元素的个数 size(); // 判断容器是否为空 empty(); // 重新指定容器的长度为 num,若容器变长,则以默认值填充新位置 // 如果容器变短,则末尾超出容器长度的元素被删除 resize(num); // 重新指定容器的长度为 num,若容器变长,则以 elem 填充新位置 // 如果容器变短,则末尾超出容器长度的元素被删除 resize(num, elem);
测试代码:
- #include
- using namespace std;
- #include
-
- void PrintList(const list<int>& L) {
- for (list<int>::const_iterator Lit = L.begin(); Lit != L.end(); ++Lit) {
- cout << *Lit << " ";
- }
- cout << endl;
- }
-
- void test() {
- list<int>L1;
-
- // 判断是否为空,为空返回 true
- if (L1.empty()) {
- cout << "L1 为空" << endl;
- }
- else {
- cout << "L1 非空" << endl;
- }
-
- L1.push_back(10);
- L1.push_back(20);
- L1.push_back(30);
- L1.push_back(40);
-
- // 判断是否为空
- if (L1.empty()) {
- cout << "L1 为空" << endl;
- }
- else {
- cout << "L1 非空" << endl;
- cout << "L1 长度:" << L1.size() << endl;
- PrintList(L1); // 10 20 30 40
-
- // resize(num),超出的用 0 填充
- L1.resize(5); // 大小从 4 变成 5
- PrintList(L1); // 10 20 30 40 0
-
- // resize(num, elem),超出的用 elem 填充
- L1.resize(6, 10); // 大小从 5 变成 6
- PrintList(L1); // 10 20 30 40 0 10
-
- // resize(num),末尾多的删除
- L1.resize(4); // 大小从 6 变成 4
- PrintList(L1); // 10 20 30 40
- }
- }
-
- int main() {
- test();
- system("pause");
- return 0;
- }
运行结果:

功能:
- 对 list 容器进行数据的插入和删除
函数原型:
// 容器末尾添加一个元素 push_back(elem); // 从容器末尾移除一个元素 pop_back(); // 从容器开头添加一个元素 push_front(elem); // 从容器开头移除一个元素 pop_front(); // 在 pos(迭代器) 位置插 elem 元素的拷贝,返回新数据的位置 insert(pos, elem); // 在 pos(迭代器) 位置插入 n 个 elem 数据,无返回值 insert(pos, n, elem); // 在 pos(迭代器) 位置插入 [beg, end) (迭代器)区间数据,无返回值 insert(pos, beg, end); // 移除容器所有数据 clear(); // 删除 [beg, end) (迭代器)区间的数据,返回下一个数据的位置 erase(beg, end); // 删除 pos (迭代器)位置的数据,返回下一个数据的位置 erase(pos); // 删除容器中所有与 elem 值匹配的元素 remove(elem);
测试代码:
- #include
- using namespace std;
- #include
-
- void PrintList(const list<int>& L) {
- for (list<int>::const_iterator Lit = L.begin(); Lit != L.end(); ++Lit) {
- cout << *Lit << " ";
- }
- cout << endl;
- }
-
- void test() {
- list<int>L1;
-
- // push_back(elem); 从尾部添加
- L1.push_back(10);
- L1.push_back(20);
-
- // push_front(elem); 从头部添加
- L1.push_front(-10);
- L1.push_front(-20);
-
- PrintList(L1); // -20 -10 10 20
-
- // pop_back(); 从尾部删除一个
- L1.pop_back();
- PrintList(L1); // -20 -10 10
-
- // pop_front(); 从头部删除一个
- L1.pop_front();
- PrintList(L1); // -10 10
-
- // insert(pos, elem); 在 pos 位置插入 elem 的拷贝,返回新数据位置
- L1.insert(L1.begin(), -20); // 开始位置插入 -20
- PrintList(L1); // -20 -10 10
-
- // insert(pos, n, elem); 在 pos 位置插入 n 个 elem 数据,无返回值
- L1.insert(L1.end(), 1, 20); // 最后一个位置插入 1 个 20
- PrintList(L1); // -20 -10 10 20
-
-
- list<int>L2;
- for (int i = 0; i < 5; i++) {
- L2.push_back(i + 1);
- }
- // insert(pos, beg, end); 在 pos 位置插入 [beg, end) 数据,无返回值
- L1.insert(L1.begin(), L2.begin(), L2.end());
- PrintList(L1); // 1 2 3 4 5 -20 -10 10 20
-
- // erase(beg, end); 删除 [beg, end) 区间数据,返回下一个数据的位置
- L1.erase(++L1.begin(), --L1.end()); // 双向迭代器,只能 ++-- ,前置才有效
- PrintList(L1); // 1 20
-
- // erase(pos); 删除 pos 位置数据,返回下一个数据的位置
- L1.erase(L1.begin());
- PrintList(L1); // 20
-
- L1.push_back(30);
-
- // clear(); 清空 list 容器数据
- L1.clear();
- if (!L1.size()) {
- cout << "L1 为空" << endl;
- }
- else {
- cout << "L1 非空" << endl;
- }
- PrintList(L1); // 空
-
-
- list<int>L3;
- L3.push_back(10);
- L3.push_back(20);
- L3.push_back(10);
- L3.push_back(20);
- L3.push_back(10);
- L3.push_back(20);
-
- // remove(num); 移除 list 容器中与 num 匹配的数据
- L3.remove(10);
- PrintList(L3); // 20 20 20
- }
-
- int main() {
- test();
- system("pause");
- return 0;
- }
运行结果:

功能:
- 对 list 容器中数据进行存取
函数原型:
// 返回第一个元素 front(); // 返回最后一个元素 back();不可以使用 [ ] 方式访问 list 容器
不可以使用 at 方式访问 list 容器
原因:本质是链表,每个数据不是用连续的线性空间存储的,迭代器也不支持随机访问
测试代码:
- #include
- using namespace std;
- #include
-
- void PrintList(const list<int>& L) {
- for (list<int>::const_iterator Lit = L.begin(); Lit != L.end(); ++Lit) {
- cout << *Lit << " ";
- }
- cout << endl;
- }
-
- void test() {
- list<int>L1;
-
- L1.push_back(10);
- L1.push_back(20);
- L1.push_back(30);
- L1.push_back(40);
-
- cout << "第一个元素: " << L1.front() << endl;
- cout << "最后一个元素:" << L1.back() << endl;
-
- // 迭代器不支持随机访问
- list<int>::iterator it = L1.begin();
-
- //it = it + 1; // × 没有与操作符 + 匹配的运算符
- //it = it++; // √
- //it = it++; // 只能这样一步一步加
- //it = it--; // √,支持双向
- }
-
- int main() {
- test();
- system("pause");
- return 0;
- }
运行结果:

功能:
- 将容器中的元素反转,以及将容器中的数据进行排序
函数原型:
// 反转链表 reverse(); // 链表排序 sort();
测试代码:
- #include
- using namespace std;
- #include
-
- void PrintList(const list<int>& L) {
- for (list<int>::const_iterator Lit = L.begin(); Lit != L.end(); ++Lit) {
- cout << *Lit << " ";
- }
- cout << endl;
- }
-
- bool myCompare(int a, int b) {
- return (a > b);
- }
-
- void test() {
- list<int>L1;
- L1.push_back(9);
- L1.push_back(5);
- L1.push_back(8);
- L1.push_back(6);
- L1.push_back(7);
-
-
- cout << "反转前:";
- PrintList(L1); // 9 5 8 6 7
-
- cout << "反转后:";
- L1.reverse();
- PrintList(L1); // 7 6 8 5 9
-
- cout << "排序前:";
- PrintList(L1); // 7 6 8 5 9
-
- cout << "排序后:";
- L1.sort(); // 从小到大,想要降序再 reverse 一下
- PrintList(L1); // 5 6 7 8 9
-
- // sort() 还有一个重载的版本,可以降序
- cout << "降序: ";
- L1.sort(myCompare);
- PrintList(L1); // 9 8 7 6 5
-
- // 所有不支持随机访问迭代器的容器,不可以使用标准算法
- // sort(L1.begin(), L1.end()); // 错误
- }
-
- int main() {
- test();
- system("pause");
- return 0;
- }
运行结果:

案例:将 Person 自定义数据类型进行排序,Person 中属性有 name、age、high
-
排序规则:按 age 进行升序,如果 age 相等就按 high 进行降序
代码实例:
- #include
- using namespace std;
- #include
- #include
-
- class Person {
-
- friend void PrintList(list
& P_List) ; - friend bool comparePerson(Person& p1, Person& p2);
- public:
- Person(string name, int age, int high) :m_Name(name), m_Age(age), m_High(high) { }
- private:
- string m_Name;
- int m_Age;
- int m_High;
- };
-
- void PrintList(list
& P_List) { - for (list
::iterator it = P_List.begin(); it != P_List.end(); ++it) { - cout << "姓名:" << (*it).m_Name << " 年龄:" << it->m_Age << " 身高:" << (*it).m_High << endl;
- }
- }
-
- // 指定排序规则
- bool comparePerson(Person& p1, Person& p2) {
- if (p1.m_Age == p2.m_Age) {
- return p1.m_High > p2.m_High;
- }
- else {
- return p1.m_Age < p2.m_Age;
- }
- }
-
- void test() {
- list
Person_List; - Person p1("李华", 18, 180);
- Person p2("张三", 19, 170);
- Person p3("王五", 20, 175);
- Person p4("赵六", 20, 170);
- Person p5("李四", 20, 180);
-
- Person_List.push_back(p1);
- Person_List.push_back(p2);
- Person_List.push_back(p3);
- Person_List.push_back(p4);
- Person_List.push_back(p5);
-
- cout << "排序前:" << endl;
- PrintList(Person_List);
- cout << "----------------------" << endl;
-
- cout << "排序后:" << endl;
- Person_List.sort(comparePerson);
- PrintList(Person_List);
- }
-
- int main() {
- test();
- system("pause");
- return 0;
- }
运行结果:
