【C++】STL----list常见用法

🔥个人主页🔥:孤寂大仙V

🌈收录专栏🌈:C++从小白到高手

🌹往期回顾🌹:C++vector常见用法

🔖 流水不争,争的是滔滔不息。

文章目录


一、list的介绍

在C++中,std::list 是一种双向链表数据结构,属于C++标准模板库(STL)中的容器之一。与std::vector相比,std::list在某些操作上有不同的性能特点,尤其是在频繁的插入和删除操作时具有优势。

list的主要特点

  1. 双向链表:std::list 是一个双向链表,意味着每个元素都有指向前后元素的指针。与数组不同,它不是连续的内存块。
  2. 高效的插入和删除:在链表中,插入和删除元素只需要修改指针,因此在任意位置插入或删除元素的效率较高,特别是当操作位置已知时(O(1)时间复杂度)。
  3. 不支持随机访问:与std::vector不同,std::list不支持通过索引直接访问元素(不能通过listi的方式访问)。如果要访问某个元素,通常需要使用迭代器来逐个遍历,效率为O(n)。

二、list的使用

list的构造


构造的list中包含n个值为val的元素

cpp 复制代码
list<int> l1(5, 1);


构造空的list

cpp 复制代码
list<int> l2;


拷贝构造函数

cpp 复制代码
list<int> l3(5,3);
list<int> l4(l3);
paint_list(l4);


用(first,list)区间的元素构造list

cpp 复制代码
vector<int> v4{ 1,2,3,4,5 };
list<int> l4(v4.begin(), v4.end());
paint_list(l4);

list的迭代器使用


begin和end返回第一个元素的迭代器+返回最后一个元素下一个位置的迭代器

rbegin和rend,rbegin是容器里的最后一个元素,rend是容器里的第一个元素。相当于begin+end迭代器反了过来。

cpp 复制代码
list<int> l5{ 1,2,3,4,5 };
list<int> l6(l5.begin(), l5.end());
list<int> l7(l5.rbegin(), l5.rend());
paint_list(l6);
paint_list(l7);

list的空间问题



判空

cpp 复制代码
list<int> l6(5, 6);
list<int> l7;
cout<<l6.empty()<<endl;
cout<<l7.empty()<<endl;


返回list中有效节点

cpp 复制代码
list<int> l7(5, 7);
cout << l7.size() << endl;

list的元素访问



返回第一个节点中值的引用
返回list的最后一个节点中值的引用

cpp 复制代码
list<int> l8{ 1,2,3,4,5 };
cout << l8.front() << endl;
cout << l8.back() << endl;

list的插入与删除



在list首元素前插入值为val的元素

cpp 复制代码
list<int> l9(5, 9);
l9.push_front(1);
paint_list(l9);


删除list中的第一元素

cpp 复制代码
list<int> l10{ 1,2,3,4,5 };
l10.pop_front();
paint_list(l10);


在list尾部插入值为val的元素

cpp 复制代码
list<int> l11{ 1,2,3,4,5 };
l11.push_back(6);
paint_list(l11);


删除list中最后一个元素

cpp 复制代码
list<int> l12{ 1,2,3,4,5 };
l12.pop_back();
paint_list(l12);


在pop位置插入值为val的元素

cpp 复制代码
list<int> lt;
lt.push_back(1);
lt.push_back(2);
lt.push_back(3);
lt.push_back(4);
lt.push_back(5);
lt.push_back(6);

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

auto it = lt.begin();
int k = 3;
while (k--)
{
	++it;
}

lt.insert(it, 30);

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


删除pos位置的元素

cpp 复制代码
list<int> lt;
lt.push_back(1);
lt.push_back(2);
lt.push_back(3);
lt.push_back(4);
lt.push_back(5);
lt.push_back(6);

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

auto it = lt.begin();
int k = 3;
while (k--)
{
	++it;
}

lt.erase(it);

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


交换两个list中的元素

cpp 复制代码
list<int> l15(15, 7);
list<int> l16(15, 8);
paint_list(l15);
paint_list(l16);

swap(l15, l16);
paint_list(l15);
paint_list(l16);


清理list中的有效元素

cpp 复制代码
list<int> l16(15, 7);
paint_list(l16);
l16.clear();
paint_list(l16);

迭代器失效问题

此处大家可将迭代器暂时理解成类似于指针, 迭代器失效即迭代器所指向的节点的无 效,即该节点被删除了 。因为 list 的底层结构为带头结点的双向循环链表 ,因此 在 list 中进行插入 时是不会导致 list 的迭代器失效的,只有在删除时才会失效,并且失效的只是指向被删除节点的迭 代器,其他迭代器不会受到影响 。

cpp 复制代码
void TestListIterator1 ()
{
int array [] = { 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 0 };
list < int > l ( array , array + sizeof ( array ) / sizeof ( array [ 0 ]));
auto it = l . begin ();
while ( it != l . end ())
{
// erase() 函数执行后, it 所指向的节点已被删除,因此 it 无效,在下一次使用 it 时,必须先给
其赋值
l . erase ( it );
++ it ;
}
}
// 改正
void TestListIterator ()
{
int array [] = { 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 0 };
list < int > l ( array , array + sizeof ( array ) / sizeof ( array [ 0 ]));
auto it = l . begin ();
while ( it != l . end ())
{
l . erase ( it ++ ); // it = l.erase(it);
}
}  

list和vector对比

相关推荐
学逆向的7 分钟前
win32注入代码
开发语言·网络安全·api·win32
wuminyu24 分钟前
ForkJoinPool窃取线程在扫描其他WorkQueue时的随机采样算法与Phase线程挂起唤醒机制解析
java·linux·c语言·jvm·c++
longlongzihan28 分钟前
链表找环:Floyd 判圈算法(LeetCode 141 & 142 )
c++·算法·leetcode·链表
Sarvartha32 分钟前
内部类知识
java·开发语言
liulilittle41 分钟前
Linux 下 select 测试函数
linux·服务器·网络·数据库·c++·select·c
FPGA小徐1 小时前
【一生一芯 / PA】异常响应机制:RISC-V 中 ecall → mtvec → mret 的完整代
开发语言·数据库·c#
北京盛世宏博1 小时前
工业环境监测选型:Modbus TCP以太网温湿度传感器部署、调试、避坑全指南
开发语言·网络·php
无忧.芙桃1 小时前
C++语言原理与实践(十二):list类的底层实现
c++·windows·list
沫璃染墨1 小时前
《Linux工程实践篇(二):线程池实战——从线程安全单例到完整源码实现》
linux·开发语言·c++·单例模式·设计模式·系统架构
泡海椒2 小时前
JQuick-Excel 多字段 TRANSFORM:让当前行字段、JContext 与展示列各归其位
开发语言·python·excel