【C++】STL容器--list的使用

目录

  • 前言
  • 一、list的介绍
  • 二、list的使用
    • [1. 构造函数和拷贝构造函数](#1. 构造函数和拷贝构造函数)
    • [2. 析构函数](#2. 析构函数)
    • [3. 赋值运算符重载operator=](#3. 赋值运算符重载operator=)
    • [4. 迭代器begin/end、rbegin/rend](#4. 迭代器begin/end、rbegin/rend)
    • [5. empty/size](#5. empty/size)
    • [6. front/back](#6. front/back)
    • [7. assign](#7. assign)
    • [8. push_front/pop_front/push_back/pop_back](#8. push_front/pop_front/push_back/pop_back)
    • [9. insert/erase](#9. insert/erase)
    • [10. swap/clear](#10. swap/clear)
    • 11.resize
    • 12.reverse
    • [13. sort](#13. sort)
    • [14. merge](#14. merge)
    • [15. unique](#15. unique)
    • [16. remove](#16. remove)
    • [17. splice](#17. splice)
  • 三、完整代码

前言

前面介绍了【C++】STL容器--vector的模拟实现详情请点击,本文将学习另一个STL容器--list,本文主要讲解list的使用

一、list的介绍

  1. list 是标准模板库(STL)中的一个容器,它实现了一个双向链表
  2. 支持在任意位置快速插入和删除元素,但不支持快速随机访问

二、list的使用

1. 构造函数和拷贝构造函数

  1. 构造函数有全缺省的构造,缺省值allocator_type()是空间配置器,避免频繁向堆上申请空间,提高效率,默认不传参即可
  2. 还可以使用n个值进行初始化
  3. 构造函数还可以使用迭代器进行初始化,迭代器可以是list类型也可以是其他类型
cpp 复制代码
void test_list1()
{
	list<int> lt1;
	list<int> lt2(5, 4);
	list<int> lt3(lt2.begin(), lt2.end());

	vector<int> v(4, 7);
	list<int> lt4(v.begin() + 1, v.end() - 1);
	list<int> lt5(lt4);
}

2. 析构函数

析构函数在list生命周期结束后自动调用完成资源清理工作

3. 赋值运算符重载operator=

  1. 注意使用赋值运算符时,list对象已经创建,否则就会调用拷贝构造函数
cpp 复制代码
void test_list2()
{
	list<int> lt1;
	list<int> lt2(5, 4);
	lt1 = lt2;
}

4. 迭代器begin/end、rbegin/rend

  1. begin/end、rbegin/rend都是获得开头或结尾位置的迭代器
cpp 复制代码
void test_list3()
{
	int a[10] = { 1, 2, 3, 4, 5 };
	list<int> lt1(a, a+ 5);

	for (auto& e : lt1)
	{
		cout << e << " ";
	}
	cout << endl;

	list<int>::iterator it = lt1.begin();
	while (it != lt1.end())
	{
		cout << *it << " ";
		++it;
	}
	cout << endl;

	list<int>::reverse_iterator it1 = lt1.rbegin();
	while (it1 != lt1.rend())
	{
		cout << *it1 << " ";
		++it1;
	}
	cout << endl;
}

5. empty/size

  1. empty:判断list是否为空
  2. size:返回有效数据个数
cpp 复制代码
void test_list4()
{
	int a[10] = { 1, 2, 3, 4, 5 };
	list<int> lt1(a, a + 5);
	list<int>lt2;
	cout << lt1.empty() << endl;
	cout << lt1.size() << endl;

	cout << lt2.empty() << endl;
	cout << lt2.size() << endl;
}

6. front/back

front/back返回list第一个位置/最后一个位置数据的引用,可以访问和修改

7. assign

assin会将数据全部清空,再重新传入你需要的数据

cpp 复制代码
void test_list5()
{
	int a[10] = { 1, 2, 3, 4, 5 };
	list<int> lt1(a, a + 5);
	list<int>lt2(3, 5);
	for (auto& e : lt2)
	{
		cout << e << " ";
	}
	cout << endl;
	lt2.assign(lt1.begin(), lt1.end());
	for (auto& e : lt2)
	{
		cout << e << " ";
	}
	cout << endl;

}

8. push_front/pop_front/push_back/pop_back

push_front/pop_front/push_back/pop_back分别是头插、头删、尾插、尾删

cpp 复制代码
void test_list6()
{
	
	list<int> lt1;
	lt1.push_front(1);
	lt1.push_front(2);
	lt1.push_front(3);
	lt1.push_front(4);
	lt1.push_front(5);
	
	lt1.pop_front();

	for (auto& e : lt1)
	{
		cout << e << " ";
	}
	cout << endl;
	lt1.push_back(6);
	lt1.push_back(7);
	
	lt1.pop_back();
	for (auto& e : lt1)
	{
		cout << e << " ";
	}
	cout << endl;
}

9. insert/erase

  1. list的insert不涉及迭代器失效问题,因为list的插入和删除是对链表节点做处理,并不会涉及异地扩容问题,但是erase会涉及迭代器失效问题,erase进行删除就是释放迭代器指向的节点,并改变节点之间的连接关系,节点被释放,那么再访问这个节点就会报错
  2. insert再迭代器位置插入一个值,并返回插入元素的迭代器;insert在迭代器位置插入n个值;insert在迭代器位置插入一段迭代区间
  3. insert在中间某个位置插入,需要使用循环迭代到那个位置再插入
  4. erase会返回一个迭代器,这个返回的迭代器是删除节点的下一个节点的迭代器,如果后续还要进行操作,可以接收这个返回值
cpp 复制代码
void test_list7()
{
	int a[10] = { 1, 2, 3, 4, 5 };
	list<int> lt1(a, a + 5);
	list<int>::iterator it = lt1.begin();
	int ret = 1;
	while (ret--)
	{
		it++;
	}
	lt1.insert(it, 8);
	for (auto& e : lt1)
	{
		cout << e << " ";
	}
	cout << endl;

	list<int> lt2(a, a + 5);
	list<int>::iterator pos = lt2.begin();
	lt2.erase(pos);
	for (auto& e : lt2)
	{
		cout << e << " ";
	}
	cout << endl;
}

10. swap/clear

  1. swap交换两个list对象数据
  2. clear清除list数据

11.resize

  • resize用于改变list的有效数据个数,当n小于当前list有效数据个数,会删除多余节点数据,当小于有效数据个数,会在list后面尾插val

12.reverse

对list数据进行逆置操作

13. sort

  1. list的sort排序底层使用的是归并排序的非递归方式,虽然算法库中也有sort,但是它只支持随机访问的迭代器:vector、string等,不支持list双向迭代器排序

迭代器分为

  • 单向迭代器:仅支持++/*
  • 双向迭代器:支持++/--/*
  • 随机访问迭代器:支持++/--/+/-/*/[]
  1. 数据量大时我们将数据存储在vector中进行排序,再copy到list中,这样比直接在list中排序效率更高

14. merge

  1. merge:将一个list对象 x 的数据归并到另一个list对象上(归并的前提是两个list对象数据必须是有序的)
  2. 归并后,x有效数据为0
cpp 复制代码
void test_list10()
{
	int a[10] = { 1, 2, 3, 4, 5 };
	list<int> lt1(a, a + 5);
	list<int> lt2;
	lt2.push_back(3);
	lt2.push_back(1);
	lt2.push_back(4);
	lt2.push_back(5);

	lt1.sort();
	lt2.sort();
	lt2.merge(lt1);
	cout << lt1.size();
	cout << endl;
	for (auto& e : lt2)
	{
		cout << e << " ";
	}
}

15. unique

  • unique:去重操作
cpp 复制代码
void test_list11()
{
	int a[10] = { 1, 1, 3, 4, 5, 5 };
	list<int> lt1(a, a + 6);
	for (auto& e : lt1)
	{
		cout << e << " ";
	}
	cout << endl;
	lt1.unique();
	for (auto& e : lt1)
	{
		cout << e << " ";
	}
}

16. remove

  • remove:移除数据为val的节点

17. splice

  1. splice:将list对象x链接到另一个list对象上,x中链接的节点就不在x上了
  2. 将x全部节点连接到pos位置
  3. 将list对象x中迭代器i的节点链接到pos位置
  4. 将一个list对象x的某个迭代器区间的节点链接到pos位置
cpp 复制代码
void test_list13()
{
	int a[10] = { 1, 1, 3, 4, 5, 5 };
	list<int> lt1(a, a + 6);
	list<int> lt2;
	lt2.push_back(7);
	lt2.push_back(12);
	lt2.push_back(1);
	lt2.push_back(3);
	lt1.splice(lt1.begin(), lt2, lt2.begin(), lt2.end());
	cout << lt2.size() << endl;
	for (auto& e : lt1)
	{
		cout << e << " ";
	}
	cout << endl;
}

三、完整代码

完整代码点击查看

相关推荐
洲覆3 小时前
基于 clangd 搭建 Redis 6.2 源码阅读与调试环境
开发语言·数据库·redis·缓存
草莓熊Lotso3 小时前
《算法闯关指南:优选算法--二分查找》--19.x的平方根,20.搜索插入位置
java·开发语言·c++·算法
旭意4 小时前
C++蓝桥杯之函数与递归
开发语言·c++·蓝桥杯
。TAT。4 小时前
C++ - vector
开发语言·c++·学习
杨福瑞4 小时前
C语言数据结构:算法复杂度(1)
c语言·开发语言·数据结构
郭源潮14 小时前
《Muduo网络库:实现one loop per thread设计模式》
开发语言·c++·网络库
linksinke4 小时前
html案例:制作一个图片水印生成器,防止复印件被滥用
开发语言·前端·程序人生·html
^_^ 纵歌4 小时前
rust主要用于哪些领域
开发语言·后端·rust
_OP_CHEN4 小时前
C++基础:(十三)list类的模拟实现
开发语言·c++·反向迭代器·stl·list·list模拟实现·vector和list对比