当前位置: 首页 > news >正文

list 接口拆解:我踩过的坑,帮你避开

个人主页:小则又沐风

个人专栏:<数据结构>

<竞赛专栏>

<C语言>
<C++>

<Linux>

座右铭

路虽远,行则将至;事虽难,做则必成

目录

前言

构造函数

迭代器

list capacity

list element access

list modifiers

总结


前言

在数据结构中我们学习了链表的相关的语法知识,并且我们用了C语言模拟实现了这个数据结构但是我们在C++中还是需要来学习一下在C++库中的链表是什么样子的,并且我们来模拟实现一下这个结构

构造函数

首先我们就来了解一下链表的构造函数

我们来一个一个看这些构造函数

list (size_type n, const value_type& val = value_type())

这个构造函数就是构造出n个节点并且这些节点的数值都是value

那么我们来代码演示一下这个构造函数的行为

#include<iostream> #include<list> using namespace std; template<class T> void print(const list<T>& t) { auto it = t.begin(); while (it != t.end()) { cout << *it << ' '; it++; } } int main() { list<int>t1(10, 8); print(t1); return 0; }

可以看出来这个构造函数的行为就是构造出的n个value的节点并且连接到一起

list()

这个构造函数就是一个无参构造他的行为就是构造出一个空的链表

#include<iostream> #include<list> #include<string> using namespace std; template<class T> void print(const list<T>& t) { auto it = t.begin(); while (it != t.end()) { cout << *it << ' '; it++; } cout << endl; } int main() { list<int>t1(10, 8); print(t1); list<string>t2; print(t2); return 0; }

list (const list& x)

这个就是大名鼎鼎的拷贝构造函数了

#include<iostream> #include<list> #include<string> using namespace std; template<class T> void print(const list<T>& t) { auto it = t.begin(); while (it != t.end()) { cout << *it << ' '; it++; } cout << endl; } int main() { list<int>t1(10, 8); print(t1); list<string>t2; print(t2); list<int>t3(t1); print(t3); return 0; }

ist (InputIterator first, InputIterator last)

这个就是可以利用其他容器的迭代器来构造

#include<iostream> #include<list> #include<string> #include<vector> using namespace std; template<class T> void print(const list<T>& t) { auto it = t.begin(); while (it != t.end()) { cout << *it << ' '; it++; } cout << endl; } int main() { list<int>t1(10, 8); print(t1); list<string>t2; print(t2); list<int>t3(t1); print(t3); vector<string>v({ "apple","banana","pear" }); list<string>t4(v.begin(), v.end()); print(t4); return 0; }

迭代器

在list中的迭代器我们可以这样来理解这个迭代器,他是一个指向一个节点的指针,因为我们知道每个节点是存储着下一个节点的指针的,所以我们的list迭代器是支持加加的,也就是把我们的指向节点的指针进行了修改

但是在实际的实现的时候我们的迭代器不仅仅是一个指针了,他是由节点的指针封装的一个类

这时候有人问了为什么必须把他封装成一个类呢?

我们需要知道的是我们在之前迭代器的使用的时候我们解引用一个迭代器得到的就是这个迭代器的数据了,但是如果我们没有对这个指针进行封装的时候我们解引用得到的就是一个节点我们要想得到数据的话我们还需要进一步的对这个节点的内容进行访问,这样就违背了我们之前的使用的习惯了

在之后的迭代器的模拟实现下我将会仔细讲解这个

我们来看看这个迭代器是怎么使用的

void print(const list<T>& t) { auto it = t.begin(); while (it != t.end()) { cout << *it << ' '; it++; } cout << endl; }

在上面的代码中我的print的模板函数就已经使用了迭代器,因为迭代器是真的一个访问容器的好东西

list capacity

下面就是有关容量的接口了

这个非常的简单

empty

判断这个链表是否为空

#include<iostream> #include<list> #include<string> #include<vector> using namespace std; template<class T> void print(const list<T>& t) { auto it = t.begin(); while (it != t.end()) { cout << *it << ' '; it++; } cout << endl; } int main() { list<int>t1(10, 8); print(t1); list<string>t2; print(t2); list<int>t3(t1); print(t3); vector<string>v({ "apple","banana","pear" }); list<string>t4(v.begin(), v.end()); print(t4); if (t1.empty()) { cout << "空" << endl; } else { cout << "非空" << endl; } return 0; }

si'ze

就是返回这个链表有多少个数据

#include<iostream> #include<list> #include<string> #include<vector> using namespace std; template<class T> void print(const list<T>& t) { auto it = t.begin(); while (it != t.end()) { cout << *it << ' '; it++; } cout << endl; } int main() { list<int>t1(10, 8); print(t1); list<string>t2; print(t2); list<int>t3(t1); print(t3); vector<string>v({ "apple","banana","pear" }); list<string>t4(v.begin(), v.end()); print(t4); if (t1.empty()) { cout << "空" << endl; } else { cout << "非空" << endl; cout << "数据个数为:" << t1.size() << endl; } return 0; }

list element access

front

返回的是头节点数据的引用

back

返回尾节点数据的引用

list modifiers

push_front

在链表的开头插入数据

void text1() { list<int>t1; t1.push_front(3); t1.push_front(2); t1.push_front(1); }

pop_front

删除头节点的数据

void text1() { list<int>t1; t1.push_front(3); t1.push_front(2); t1.push_front(1); t1.pop_front(); }

push_back

在链表的尾部进行插入数据

void text2() { list<int>t2; t2.push_back(1); t2.push_back(2); t2.push_back(3); t2.push_back(4); t2.push_back(5); }

pop_back

删除尾节点

void text2() { list<int>t2; t2.push_back(1); t2.push_back(2); t2.push_back(3); t2.push_back(4); t2.push_back(5); t2.pop_back(); }

insert

在pos的位置插入数据

需要注意的是这个函数的返回值是插入数据的迭代器

void text3() { list<int>t3; t3.insert(t3.begin(), 100); t3.insert(++t3.begin(), 100); }

erase

删除pos位置的节点

void text3() { list<int>t3; t3.insert(t3.begin(), 100); t3.insert(++t3.begin(), 100); t3.erase(t3.end()); }

这个函数的返回值是删除节点的下一个节点

需要注意的是如果我们删除了一个节点但是我们并没有对这个节点的迭代器进行更新的话,我们再去对这个迭代器访问的时候就会造成迭代器失效的问题

swap

交换两个链表的元素

void text4() { list<int>t1({ 1,2,3 }); list<int>t2(10, 8); t1.swap(t2); }

clear

清理掉链表中的有效的数据

void text4() { list<int>t1({ 1,2,3 }); list<int>t2(10, 8); t1.swap(t2); t1.clear(); }

总结

本章节聚焦std::list的核心修改接口,系统梳理了链表节点增删、替换与重组的各类操作。从基础的头尾插入删除push/pop,到迭代器区间操作insert/erase,再到链表专属的splicemergesort等高级功能,完整覆盖了 STL list 容器的修改能力。

之后我会模拟实现一下这个链表.

谢谢大家的观看!!!

http://www.jsqmd.com/news/723580/

相关文章:

  • 问卷设计大比拼:手工瞎编 vs 通用 AI vs 虎贲等考 AI|学术实证真正的差距在这里
  • 2026年全行业楼宇自控系统 10 大权威排名 楼宇自控厂家深度评测
  • 零依赖多市场股票行情查询工具:Python标准库实现与OpenClaw集成
  • 苹果App上架4.3a被拒解决方案汇报总结
  • 充电桩ODM合作:客户关注点解析
  • Java学习19
  • 告别VoxelNet!用PointPillars+KITTI数据集,手把手教你搭建自己的3D目标检测模型
  • 用51单片机+TLC549做个简易电压表:从SPI时序到数码管显示的保姆级教程
  • 基于Aristotle框架构建多智能体工作流:从原理到实践
  • 啤酒招商加盟:酒水代理加盟、酒水招商加盟、鲜啤招商加盟、县城创业好项目、啤酒代理加盟、啤酒区域代理、啤酒厂家直招选择指南 - 优质品牌商家
  • 别再为无序数据发愁了!用PyTorch手把手实现Deep Sets处理点云分类(附完整代码)
  • LeetCode深度解析:从算法原理到工程实践的系统学习指南
  • 上班摸鱼神器:一分钟学会一个上班摸鱼的OpenClaw Skill技能之今日热点新闻
  • 为什么要做大模型粘性调度?
  • 音节划分中常用前缀列表总结
  • R语言数据报告效率提升300%?Tidyverse 2.0五大隐藏更新+实战Pipeline重构(附GitHub可运行模板)
  • 6FC5203-0AF02-0AA0操作员面板
  • GitHub Stacked PRs:重塑现代软件开发的工作流革命
  • 【R语言偏见检测权威指南】:20年统计专家亲授LLM公平性评估的7大核心检验与调优公式
  • MoS动态路由机制:多模态扩散模型的融合突破
  • 2026年控糖大米批发可靠品牌TOP5权威排行 - 优质品牌商家
  • 2026年国内玉米加工设备标杆推荐:核心参数与场景适配全解析 - 优质品牌商家
  • TwinCAT项目打包
  • 【2026实战】AI Agent技术全景与核心组件解析:Python+Go构建企业级AI Agent实战指南
  • 避坑指南:2ASK解调中的均值滤波与同步判决,如何用HLS在FPGA上稳定实现?
  • 爬虫开发者必备:claw-shield反反爬虫工具核心架构与实战配置指南
  • 别再死磕UDF了!Fluent内置Lee模型搞定沸腾冷凝,手把手教你从零配置
  • 针对你日志中 Referer 为空 的情况,这里做一个详细解释
  • 拆解物料管理erp系统的核心功能,看物料管理erp系统如何解决库存积压与缺料难题
  • golang如何理解协程调度抢占机制_golang协程调度抢占机制技巧