C++容器list

C++容器list

定义

std::list - cppreference.cn - C++参考手册

  • 双向链表:每个元素(节点)包含数据、一个指向前一个节点的指针和一个指向后一个节点的指针
  • 非连续存储:元素在内存中不是连续存放的,而是通过指针链接
  • 高效修改 :插入和删除操作(包括中间位置)的时间复杂度为 O(1),前提是已知插入/删除位置的迭代器
  • 不支持随机访问 :不能通过下标 [] 直接访问第 n 个元素,必须从头或尾遍历,时间复杂度为 O(n)
  • 稳定迭代器 :只要不删除元素,插入操作不会使其他元素的迭代器、指针或引用失效。这是 list 相对于 vector 和 deque 的巨大优势

构造函数

1、默认构造函数

创建空的list,长度为0

cpp 复制代码
int main()
{
	system("chcp 65001");
	list<std::u8string> list1;

	cout << "list1.size()= " << list1.size() << endl;
	cout << "list1.max_size()= " << list1.max_size() << endl;
}

2、指定大小构造函数

cpp 复制代码
std::string getStringFromU8string(const std::u8string& u8str) {
	return std::string(reinterpret_cast<const char*>(u8str.data()), u8str.size());
}

std::u8string getU8stingFromString(const std::string& str) {
	return std::u8string(reinterpret_cast<const char8_t*>(str.data()), str.size());
}

int main()
{
	system("chcp 65001");
	list<std::u8string> list1(4);

	cout << "list1.size()= " << list1.size() << endl;
	cout << "list1.max_size()= " << list1.max_size() << endl;
	for (auto it : list1)
	{
		cout << "list1-> " << getStringFromU8string(it) << endl;
	}
}

3、指定大小与初始值构造函数

cpp 复制代码
int main()
{
	system("chcp 65001");
	list<std::u8string> list1(4, u8"&&");

	cout << "list1.size()= " << list1.size() << endl;
	cout << "list1.max_size()= " << list1.max_size() << endl;
	for (auto it : list1)
	{
		cout << "list1-> " << getStringFromU8string(it) << endl;
	}
}

4、拷贝构造函数

cpp 复制代码
int main()
{
	system("chcp 65001");
	list<std::u8string> list1 = { u8"北京", u8"上海", u8"广州", u8"深圳" };
	// 拷贝构造函数
	list<std::u8string> list2(list1);

	cout << "list2.size()= " << list2.size() << endl;
	cout << "list2.max_size()= " << list2.max_size() << endl;
	for (auto it : list2)
	{
		cout << "list2-> " << getStringFromU8string(it) << endl;
	}
}

5、移动构造函数‌

cpp 复制代码
int main()
{
	system("chcp 65001");
	list<std::u8string> list1 = { u8"北京", u8"上海", u8"广州", u8"深圳" };
	// 移动构造函数
	list<std::u8string> list2(std::move(list1));

	cout << "list2.size()= " << list2.size() << endl;
	cout << "list2.max_size()= " << list2.max_size() << endl;
	for (auto it : list2)
	{
		cout << "list2-> " << getStringFromU8string(it) << endl;
	}

	cout << "list1.size()= " << list1.size() << endl;
	cout << "list1.max_size()= " << list1.max_size() << endl;
}

6、范围构造函数

cpp 复制代码
int main()
{
	system("chcp 65001");
	std::array<std::u8string, 4> arr1 = { u8"北京", u8"上海", u8"广州", u8"深圳" };

	// 范围构造函数
	list<std::u8string> list1(arr1.rbegin(), arr1.rend());

	cout << "list1.size()= " << list1.size() << endl;
	cout << "list1.max_size()= " << list1.max_size() << endl;
	for (auto it : list1)
	{
		cout << "list1-> " << getStringFromU8string(it) << endl;
	}
}

7、指定初始化列表构造函数

cpp 复制代码
int main()
{
	system("chcp 65001");
	list<std::u8string> list1 = { u8"北京", u8"上海", u8"广州", u8"深圳" };
	list<std::u8string> list2{ u8"张三", u8"李四" };

	cout << "list1.size()= " << list1.size() << endl;
	cout << "list1.max_size()= " << list1.max_size() << endl;
	for (auto it : list1)
	{
		cout << "list1-> " << getStringFromU8string(it) << endl;
	}
}

元素访问

不支持下标访问

函数 描述
front() 返回第一个元素的引用。
back() 返回最后一个元素的引用。
cpp 复制代码
int main()
{
	system("chcp 65001");
	list<std::u8string> list1 = { u8"北京", u8"上海", u8"广州", u8"深圳" };

	cout << "list1.size()= " << list1.size() << endl;
	cout << "list1.max_size()= " << list1.max_size() << endl;
	cout << "list1.front()= " << getStringFromU8string(list1.front()) << endl;
	cout << "list1.back()= " << getStringFromU8string(list1.back()) << endl;
}

容量大小

函数 描述
empty() 如果 list 为空,返回 true。
size() 返回当前元素数量。
max_size() 返回容器可容纳的最大元素数量。
cpp 复制代码
int main()
{
	system("chcp 65001");
	list<std::u8string> list1 = { u8"北京", u8"上海", u8"广州", u8"深圳" };

	cout << "list1.empty()= " << boolalpha << list1.empty() << endl;
	cout << "list1.size()= " << list1.size() << endl;
	cout << "list1.max_size()= " << list1.max_size() << endl;
	cout << "list1.front()= " << getStringFromU8string(list1.front()) << endl;
	cout << "list1.back()= " << getStringFromU8string(list1.back()) << endl;
}

迭代器

begin-end与rbegin-rend

cpp 复制代码
int main()
{
	system("chcp 65001");
	list<std::u8string> list1 = { u8"北京", u8"上海", u8"广州", u8"深圳" };

	// for循环
	for (auto it : list1)
	{
		cout << "list1-> " << getStringFromU8string(it) << endl;
	}

	//begin-end
	for (auto it = list1.begin(); it != list1.end(); it++)
	{
		cout << "begin-end list1-> " << getStringFromU8string(*it) << endl;
	}

	//cbegin-cend
	for (auto it = list1.cbegin(); it != list1.cend(); it++)
	{
		cout << "cbegin-cend list1-> " << getStringFromU8string(*it) << endl;
	}

	//rbegin-rend
	for (auto it = list1.rbegin(); it != list1.rend(); it++)
	{
		cout << "rbegin-rend list1-> " << getStringFromU8string(*it) << endl;
	}
}

修改操作

函数 描述
push_back(value) 在末尾插入一个元素
push_front(value) 在开头插入一个元素。
pop_back() 删除最后一个元素。
pop_front() 删除第一个元素。
emplace_back(args...) 在末尾就地构造一个元素(不用复制)
emplace_front(args...) 在开头就地构造一个元素(不用复制)
emplace(pos, args...) 在位置 pos 就地构造一个元素(不用复制)
insert(pos, value) 在位置 pos 插入一个元素。
insert(pos, n, value) 在位置 pos 插入 n 个 value。
insert(pos, first, last) 在位置 pos 插入范围 [first, last) 的元素。
erase(pos) 删除位置 pos 的元素,返回下一个元素的迭代器。
erase(first, last) 删除范围 [first, last) 的元素,返回 last 迭代器。
clear() 删除所有元素。
resize(n) 调整大小到 n。如果变大,新元素用默认值初始化(小于实际元素个数,会删除后面的元素)
swap(other) 与另一个 list 交换内容。
cpp 复制代码
int main()
{
	system("chcp 65001");
	list<std::u8string> list1 = { u8"北京", u8"上海", u8"广州", u8"深圳" };
	//头部添加数据
	list1.push_front(u8"哈尔滨");
	list1.emplace_front(u8"长春");

	// 尾部添加数据
	list1.push_back(u8"沈阳");
	list1.emplace_back(u8"葫芦岛");
	for (auto it : list1)
	{
		cout << "list1-> " << getStringFromU8string(it) << endl;
	}

	// 删除元素
	list1.pop_front();
	list1.pop_back();
	// 删除第一个
	list1.erase(list1.begin());
	// 删除第三个	
	list1.erase(std::next(list1.begin(), 2));
	// 清空list
	list1.erase(list1.begin(), list1.end());
	for (auto it : list1)
	{
		cout << "after delete, list1-> " << getStringFromU8string(it) << endl;
	}

	// 插入数据
	list1.insert(list1.begin(), u8"测试1");
	list1.insert(std::next(list1.begin(), 1), u8"测试2");
	list1.insert(std::next(list1.begin(), 2), 2, u8"&&");

	std::array<std::u8string, 2> arr1 = { u8"张三",u8"李四" };
	list1.insert(list1.begin(), arr1.begin(), arr1.end());
	for (auto it : list1)
	{
		cout << "after insert, list1-> " << getStringFromU8string(it) << endl;
	}

	// 调整大小
	list1.resize(2);
	cout << "list1.size()= " << list1.size() << endl;
	cout << "list1.max_size()= " << list1.max_size() << endl;
	for (auto it : list1)
	{
		cout << "after resize, list1-> " << getStringFromU8string(it) << endl;
	}
	list1.clear();
}

链表操作

函数 描述
splice(pos, other, it) 将 other 中 it 指向的元素移动到 l 的 pos 位置。O(1)
splice(pos, other, first, last) 将 other 中 [first, last) 范围的元素移动到 l 的 pos 位置。O(1)
remove(value) 删除所有值为 value 的元素。
remove_if(pred) 删除所有满足谓词 pred 的元素。
unique() 删除连续的重复元素(只保留一个)。
unique(pred) 使用自定义比较函数删除连续的重复元素。
sort() 对元素进行排序(默认升序)。
sort(comp) 使用自定义比较函数排序。
reverse() 反转 list 中元素的顺序。
merge(other) 将已排序的 other 合并到 l 中,并保持有序。other 变为空。
cpp 复制代码
int main()
{
	system("chcp 65001");
	list<std::u8string> list1 = { u8"北京", u8"上海", u8"广州", u8"深圳" };
	list<std::u8string> list2 = { u8"张三",u8"李四" };
	// 将list2的第一个元素移动到list1的第一个位置
	list1.splice(list1.begin(), list2, list2.begin());

	// 将list2的前两个元素移动到list1的第一个位置
	// list1.splice(list1.begin(), list2, list2.begin(), list2.end());
	for (auto it : list1)
	{
		cout << "afet splice, list1-> " << getStringFromU8string(it) << endl;
	}

	// 删除排序
	list1.remove(u8"张三");
	list1.sort();
	for (auto it : list1)
	{
		cout << "afet sort, list1-> " << getStringFromU8string(it) << endl;
	}

	// 转置
	list1.reverse();
	for (auto it : list1)
	{
		cout << "afet reverse, list1-> " << getStringFromU8string(it) << endl;
	}

	// 合并另外一个list(要求已经排好序)
	list1.sort();
	list2.sort();
	list1.merge(list2);
	cout << "afet merge, list1.size()= " << list1.size() << endl;
	cout << "afet merge, list2.size()= " << list2.size() << endl;
}

其他

特性 std::list std::vector std::deque
任意位置插入/删除 O(1) (已知位置) O(n) O(n) (中间) / O(1) (首尾)
头部插入/删除 O(1) O(n) O(1)
尾部插入/删除 O(1) O(1) 均摊 O(1)
随机访问 不支持 O(1) O(1)
内存布局 非连续 (链表) 连续 分段连续
迭代器失效 仅被删除元素的迭代器失效 插入/删除可能导致大量失效 插入/删除可能导致大量失效
splice 操作 O(1) 不支持 不支持
内存开销 高 (每个元素有额外的指针开销) 低 中等
缓存局部性 差 好 中等
相关推荐
anew___3 分钟前
《从零手写操作系统 (20):ELF加载器——让OS读懂现代编译器》
java·服务器·前端
code2cat4 分钟前
【随笔】MCP资源更新订阅:通知到达以后,Agent怎样刷新旧资料
java·后端·开发工具·ai agent·mcp
汉克老师13 分钟前
GESP2026年9月认证C++一级( 第二部分判断题(1~10题)精讲
c++·gesp·小学生·学c++编程
一只旭宝1 小时前
C++ 后端开发面试题整理
java·c++·面试
xlq223221 小时前
全面复习1
c++
Dylan的码园1 小时前
求平均成绩 矩阵数据处理 【循环处理 二维数组】
c++·线性代数·矩阵
sunshine22 girl1 小时前
Java学习五 面向对象高级5 内部类3-静态内部类和局部内部类(了解)
java·学习
en.en..1 小时前
Linux 进程退出exit(函数)
java·开发语言·算法
李游Leo1 小时前
HarmonyOS 7 TaskPool + Node-API + zstd:Native 批量压缩任务的主线程隔离、进度回传与资源收口【鸿蒙心迹】
java·华为·harmonyos
Light Gao1 小时前
Encoder 与 Decoder 详解:从 Embedding 到 Seq2Seq 的完整数据流
java·开发语言·embedding