C++ list双向带头循环链表完全指南

《C++ list 完全指南:list的模拟实现》 本文介绍了C++ list 完全指南中0list的模拟实现,期待你的关注! 阅读详情

1. 什么是 list?

std::list 是 STL 提供的双向链表容器,每个元素存放在一个独立的节点中,节点之间通过指针链接。结构特点:

  • 内存不连续,不支持随机访问(没有 [] 和 at())。

  • 在任意位置插入或删除元素都非常高效,时间复杂度 O(1)(前提是你已经拥有指向该位置的迭代器)。

  • 不需要像 vector 那样扩容或移动元素,插入后其他元素的地址不会改变。

  • 自带一些高效的成员函数:sort、merge、reverse、splice(拼接)、remove、unique 等。

一句话概括:当程序频繁在序列中间插入或删除元素,且不需要随机访问时,优先考虑 list。


2. 引入头文件与基本声明

使用 list 前,必须包含头文件:

#include <list>

声明一个 list 对象:

std::list<int> lst;              // 存放 int 的空链表
std::list<std::string> words;    // 存放字符串
std::list<double> prices;        // 存放价格

同样,我们用 std:: 前缀,保持代码清晰。


3. 初始化方法

list 的初始化与 vector 基本一致:

list<int> l1;                     // 空链表
list<int> l2(5);                  // 5 个元素,默认值 0
list<int> l3(5, 10);              // 5 个元素,都是 10
list<int> l4 = {1, 2, 3, 4};      // 列表初始化
list<int> l5(l4);                 // 拷贝构造
list<int> l6(l4.begin(), l4.end());// 用迭代器范围构造

注意:list 没有类似 vector 的 capacity() 和 reserve(),因为它根本不需要预分配连续内存。


4. 常用操作详解

list 比 vector 多了很多首部操作,而且有自己专属的算法成员。

4.1 添加元素

list<int> lst;

// 尾部添加
lst.push_back(30);
lst.emplace_back(40);     // 原地构造,更高效

// 首部添加
lst.push_front(20);
lst.emplace_front(10);

// 任意位置插入
auto it = lst.begin();
++it;                     // 移动到第二个位置
lst.insert(it, 25);       // 在迭代器前插入 25
lst.insert(it, 2, 7);     // 插入两个 7
lst.insert(it, {1,2,3});  // 插入初始化列表(C++11)

因为 list 是双向链表,在头部操作非常快,这是 vector 做不到的(vector 头插要移动所有元素)。

4.2 访问元素

list 不提供随机访问,只能访问头尾:

int first = lst.front();   // 第一个元素
int last  = lst.back();    // 最后一个元素

如果要访问中间元素,必须使用迭代器逐一遍历。下面这样是错误的:

// int x = lst[2];        // 编译错误!list 没有 operator[]

4.3 删除元素

lst.pop_back();            // 删除尾部元素
lst.pop_front();           // 删除头部元素

// 删除指定迭代器所指元素
auto it = lst.begin();
++it;
lst.erase(it);             // 返回下一个有效迭代器

// 删除所有值为 val 的元素
lst.remove(10);            // 删除所有等于 10 的元素

// 按条件删除(C++11 的 lambda 很方便)
lst.remove_if([](int x) { return x % 2 == 0; }); // 删除所有偶数

lst.clear();               // 清空链表

注意 remove 是 list 的成员函数,它会真正删除节点并调整链接,与头文件 <algorithm> 中的泛型 std::remove 不同(后者只是移动元素,不改变容器大小)。

4.4 其他特色操作

list 还有一些独门绝技,特别适合某些算法:

// 反转链表
lst.reverse();

// 排序(list 自带的 sort,效率优于 std::sort)
lst.sort();                         // 默认升序
lst.sort(std::greater<int>());      // 降序

// 合并两个已排序链表(合并后,另一个链表为空)
list<int> other = {2,4,6};
lst.merge(other);                   // 要求两个链表都已排序

// 移除连续重复元素(通常配合 sort 使用)
lst.unique();                       // 只保留连续相同元素中的第一个

// 拼接(splice)—— 将另一个链表的元素整个移动到指定位置
list<int> extra = {100, 200};
auto pos = lst.begin();
++pos;
lst.splice(pos, extra);             // extra 中所有元素移到 pos 前,extra 变空

splice 是 list 的一大亮点:它将另一个链表的节点“偷”过来,只修改指针,不复制元素,效率极高。实现复杂的数据结构(如 LRU 缓存)时非常有用。


5. 遍历 list

因为没有下标,我们主要使用范围 for 循环或迭代器。

范围 for(推荐)

for (int x : lst) {
    cout << x << " ";
}

需要修改元素时用引用:

cpp

for (int& x : lst) {
    x *= 2;
}

迭代器

for (auto it = lst.begin(); it != lst.end(); ++it) {
    cout << *it << " ";
}

list 的迭代器是双向迭代器,可以 ++ 和 --,但不能 it += 3 这样随机移动。如果需要跳过多个元素,只能循环递增。

6. list 的内存管理特点

  • 非连续内存:每个元素是独立的节点,节点中包含数据以及指向前驱和后继的两个指针。因此 list 占用的总内存比 vector 多(多出指针开销)。

  • 没有 capacity 和 reserve:添加元素时就分配一个新节点,删除时立即释放节点内存。

  • 迭代器稳定性:在 list 上插入或删除元素不会导致其他元素的迭代器失效(当然,被删除的那个元素自己的迭代器会失效)。这一点比 vector 安全得多,vector 扩容会让所有迭代器失效。

  • 不能通过下标访问:访问第 n 个元素需要从头(或尾)遍历 n 步,复杂度 O(n)。因此不要用 list 做频繁的随机访问操作。

7. 常见误区与注意事项

  1. 试图用 [] 访问元素
    list 没有 operator[],编译错误。请用迭代器或范围 for。

  2. 对 list 使用全局 std::sort

    std::sort(lst.begin(), lst.end()); // 错误!list 迭代器不是随机访问迭代器

    必须用成员函数 lst.sort()。

  3. 删除元素时迭代器失效
    类似 vector,erase 会返回下一个有效迭代器,正确写法:

    for (auto it = lst.begin(); it != lst.end(); ) {
        if (需要删除 *it) {
            it = lst.erase(it);
        } else {
            ++it;
        }
    }

    如果写成 lst.erase(it); ++it;,it 已经失效,程序会崩溃。

  4. remove 与全局 std::remove 的混淆
    使用 lst.remove(value) 是 O(n) 删除所有匹配节点,真正改变大小;而 std::remove 配合 erase 是另一种惯用法,但不适用于 list(而且更繁琐)。建议在 list 上就用成员 remove。

  5. 误以为 list 总是比 vector 快
    链表的插入删除是 O(1),但找到插入位置可能需要 O(n) 的遍历。而且链表的内存分散,缓存局部性差,遍历速度远不如 vector。实际选择时要基于场景。

  6. unique 只移除连续的重复
    如果希望移除所有重复元素,需要先排序

8. 小结

  • list 是双向链表,头尾操作和任意位置插入删除极快。

  • 不支持随机访问,没有 [],遍历速度不如 vector。

  • 自带 sort、merge、reverse、splice、remove、unique 等高效成员函数。

  • 插入删除不导致其他迭代器失效,这是它的重要安全优势。

  • 选择合适的容器:需要随机访问用 vector,频繁中间插入删除用 list。

可以这样理解:vector 是你的瑞士军刀,list 是你的手术刀——各有专长。

循环链表c++ 使用c++语言实现的循环链表,功能齐全,包括插入、删除、寻找等功能 立即下载

相关推荐

20个闭环渗透测试项目:从漏洞发现到简历突围

渗透测试不仅是工具使用,更是对系统设计缺陷与实现偏差的深度推演。理解OWASP Top 10、Burp Suite等基础能力只是起点,真正具备工程价值的是能复现、可验证、可协作的完整攻击链。本文聚焦真实业务场景下的SSRF协议绕过、JWT签名机制缺陷、Redis未授权利用、Kong网关配置风险及etcd存储结构分析等核心热词,揭示漏洞本质在于架构决策与配置偏差的叠加态。适用于红队实战、甲方安全建设与乙方渗透审计等多类岗位,帮助从业者将技术动作升维为技术叙事。

weixin_32234493的博客 415

【数据结构与算法】- 循环链表 - 详细实现步骤及代码(C/C++)

本文介绍循环链表的基础概念,以及一步步说明怎样实现一个循环链表,最后给出C语言实现代码

wkd_007的博客 1万+

S4-FPGA-K7板级原理图硬件实战

xilinx K7板级硬件实战

weixin_66510961的博客 6154

【C++】STL容器 list——双向带头循环链表的简单实现

STL 链表

weixin_67312366的博客 2571

Unity学习笔记之【IK反向动力学操作】

反向动力学,简称IK。相较于正向动力学,反向动力学旨在子级对父级产生的影响。使用IK,可以实现根据目标位置或方向来计算并调整角色的关节(骨骼)链,以使角色的末端(如手臂、腿部等)达到预期的位置或取向。通过使用 Unity 的 IK 功能,你可以实现各种复杂的角色动画效果,如角色抓取、足部对齐、手臂跟随等。 2. 将所视的目标物体拖拽绑定 4. 实现效果如下 :移动角色时注释立方体 实现效果如下

m0_47351846的博客 2955

当预编译包失效时:手把手教你在Nvidia Orin (JetPack 5.1.1) 上源码编译onnxruntime-gpu

本文详细指导在Nvidia Orin (JetPack 5.1.1) 上源码编译onnxruntime-gpu的全流程,解决预编译包兼容性问题。涵盖环境准备、工具链配置、源码编译、常见问题解决及性能优化技巧,帮助开发者在边缘计算设备上实现高效AI模型推理。

weixin_29062823的博客 135

双向循环链表list(C++)

双向循环链表list(C++)

那年聪聪 2067

iPhone存储空间耗尽自救指南:从“白苹果”死锁到成功保数据刷机

本文详细介绍了iPhone存储空间耗尽导致'白苹果'死锁的解决方案,通过保留数据刷机方法成功恢复设备运行。文章分享了从失败尝试到最终成功的完整流程,包括关键操作步骤和预防措施,帮助用户在紧急情况下保住重要数据。

weixin_32578161的博客 290

循环链表(C++实现)

循环链表内容整理

st66688的博客 3829

MATLAB基础应用精讲-【数模应用】信用评分模型(附R语言和python代码实现)

信用评分模型是近年来兴起的一种为了保障银行和其他金融部门的金融安全而设立的一种关于人身金融权限的划定模型。该模型指根据客户的信用历史资料,利用一定的信用评分模型,得到不同等级的信用分数,根据客户的信用分数,来决定客户所可以持有的金额权限,从而保证还款等业务的安全性。而随着在现代社会和公司中,贷款,信用卡的作用日渐突出,信用评分模型的发展前景不可估量。信贷风险是指借款人因偿还贷款或履行合同承诺而破产而产生损失的可能性。传统上,它与贷款人无法偿还所欠利息和本金、影响现金流和增加装配成本所产生的风险有关。

qq_36130719的博客 364

〖Python接口自动化测试实战篇④〗- 接口自动化测试详解

[接口测试] 是相对来说和我们的功能测试 [最为接近的一种自动化测试手段] ,所以我们首先来学习接口测试的内容。 实现接口的开发与接口的测试,在我们的思维上、想法上、面向的态度上都是不一样的。所以大家要有一个思维上的转换,要认识了解一下 接口测试到底是做什么的、它的功能、意义在哪里。...

易编橙 · 终身成长社群,相遇已是上上签! 5万+

C++单链表

根据单链表的相关知识,借鉴了单链表C++实现代码_阿大古的博客-优快云博客_链表c++实现的内容,写了一个C++单链表的实现。 目前因为typedef int datatype了,所以是整型的单链表,我改了typedef float datatype也简单试了以下没什么问题,但是改成float后cout那里要设置一下保留几位小数,不然打印出来的结果也可能有点偏差。 第一次写,可能存在问题,欢迎大家批评指正,我个人比较好奇是否有内存泄漏,或者哪一步有降低复杂度的可能,也请提出意见嘿嘿。 我个人喜欢分文

weixin_45806071的博客 402

UNet 改进(45):轻松集成Triplet Attention,让分割效果起飞!

本文介绍了一种在U-Net架构中集成CSRA残差注意力模块的方法。该模块通过结合通道注意力和空间注意力机制,在U-Net的瓶颈层对特征进行自适应重标定,使网络聚焦于关键区域。文章详细解析了代码实现,包括基础构建块DoubleConv、核心CSRA模块原理及其在U-Net中的战略位置集成。测试表明该模型能保持标准U-Net的输入输出维度,同时通过注意力机制提升特征选择能力。这种模块化设计便于在不同任务中应用,为图像分割领域提供了有效的注意力增强方案。

2401_82355416的博客 104

【C++STL详解】带头双向循环结构 + 双向迭代器,核心接口 + 排序效率 + 避坑指南

本文详解 C++ STL 中 list 容器:基于带头双向循环链表,双向迭代器仅支持 ++/--,不支持随机访问。涵盖构造函数、emplace_back/push_back、insert/erase 等核心接口,解析 splice 节点转移、merge 合并有序链表、unique 去重(需先排序)等特性。对比排序效率,指出 list 自带 sort 远不及 vector 中转方案。总结其适合频繁插入删除的场景及使用避坑点

2402_87731470的博客 2310

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

【C++】第十二节—详解list(list的介绍和使用、模拟实现)

本文介绍了C++中list容器的使用和模拟实现。主要内容包括:1) list的基本概念,它是带头双向循环链表;2) list的常用接口,如构造、迭代器、容量操作、元素访问和修改操作;3) push_back和emplace_back的区别,后者在某些情况下更高效;4) vector和list在排序性能上的差异,vector的排序效率更高;5) 通过代码示例演示了list的模拟实现过程,包括节点结构、迭代器和基本操作。文章还提供了完整的测试代码,帮助理解list的实际应用。作者作为C++学习者,将持续更新相关

稻草人 2614

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

【C++】 list 实现:双向循环链表解析

摘要: 本文深入剖析C++ STL中list容器的底层实现与使用方法。list基于双向循环链表结构,具有高效插入删除(O(1))和无需扩容的特点,与vector形成互补。文章详细讲解了list的核心特性、迭代器使用、多种构造方式、容量查询与元素访问方法,以及增删查改操作接口。通过对比vector,突出list在非连续存储和指针操作方面的优势,并强调其迭代器不支持随机访问的特殊性。代码示例展示了list的实际应用场景,为理解链表底层逻辑提供了实践参考。

yuuki233233的博客 1175

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

List-带头结点的双向循环链表

STL库中常用的封装好的string(专门用来处理字符串)以及vector(储存任意类型)还有list。前两种在存储空间上地址都是连续的,但是list存储地址不一定是连续的,list的底层实际是用一个带头双向循环链表实现下面为了更加深入了解学习list先手动写一个带头双向循环链表。下面是我用C++写的。

Yyuan12345678的博客 980

【c++深入系列】:万字详解list(附模拟实现的list源码)

想要学会c++的list,看这篇文章就够了!

努力努力再努力wz的博客 1488

【C++】——list 容器的解析与极致实现

人的一切痛苦,本质上都是对自己的无能的愤怒。—— 王小波是C++(STL)中的一个成员,其。不同于连续的、紧密排列的数组容器,List容器的内部是由双向链表构成的,使得它在插入和删除操作上,就如同行云流水一般顺畅,不需移动其它元素。环状链表的尾是一个空节点,符合“左闭右开”区间。需要频繁进行插入和删除操作的场合。更多地需要随机访问元素。

2402_82668782的博客 3935

C++ list

本文介绍了C++ STL中的list容器,主要内容包括:1. list作为双向链表的基本特性,支持高效插入删除但随机访问性能差;2. list的使用方法,包括构造方式、迭代器类型(双向迭代器)、空间操作、元素访问和增删改查等接口;3. list迭代器失效问题,仅删除操作会导致被删节点的迭代器失效;4. 通过模板和运算符重载实现迭代器与const迭代器;5. 完整模拟实现list容器,包含节点结构、迭代器封装及各种成员函数。文章着重讲解了list与vector/string的区别,特别是迭代器实现方式的差异,

naobeng的博客 1929

C++中的list(2)简单复现list中的关键逻辑

这一节的主要内容就是:简单复现list中的关键逻辑。同样的,我们这一节也是先粗略的看一眼源码,结合源码,边理解边复现。源码我已经上传到gitee,网址如下:Murphy/博客存档,我们主要看的就是其中的其次就是这一节是有难度的,但是难度很高吗?也不是很高,我尽量捋顺了给大家说清楚。这一节最主要的几个知识点就是:模板、封装、以及数据结构的逻辑。这一部分大家可看可不看,这是我自己梳理的一个逻辑过程,帮助我自己理解list的。大家感兴趣可以看一下,当然也可以直接跳过这部分。首先我们知道list容器是一个带头双向循

LXdian_LX的博客 1534

【c++丨STL】list的使用

之前我们已经学习了string、vector两个容器的使用方法及模拟实现,今天跟大家介绍list的使用方法。在STL中,尽管容器各异,但同名接口的功能往往是相似的。因此,在我们掌握了少数几个容器的使用方法后,对于未曾接触过的其他容器,只要了解其底层数据结构,就基本能够上手使用它们。list是STL中的一种容器,用于表示链表结构,底层实现是一个双向带头循环链表。

2301_80955819的博客 2184

C++ list类

list的底层结构是双向带头循环链表。

2301_80758704的博客 1101

【C++】深入剖析list:list及其双向迭代器实现

本文介绍了C++ STL中的list容器及其模拟实现的要点。深度解析了list迭代器的封装和原理。同时验证了list的成员函数sort的效率陷阱

2502_94043640的博客 538

【C++初阶】list的模拟实现 附源码

【C++初阶】list的模拟实现 附源码

旋律 | 话语 | 色彩 | 情景 1360

几分钟彻底了解单链表、带头链表、双向链表、循环链表、带头双向循环链表速通,知识解析与实现。

图解如果都给Node1-Node3都附加上一个地址的话,那可以更加直观的理解链表的结构。所以next指向的是一个地址,而且还是结构体的地址。结构体为:}Node;应用方面:如队列的实现等,对于需要用到链表的时候都先优先考虑不带头节点的单链表,因为结构简单,满足需求就可以了。

loneplayer的博客 747
上一篇: C++ vector动态数组完全指南
下一篇: C++容器适配器:stack与queue详解
CCCCCCCCharlie
博客等级 码龄1年 2粉丝 28原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值