C++_STL之list篇
一、list的介绍
std::list是C++标准模板库(STL)中的一个双向链表容器。与vector和deque不同,list不支持随机访问,但它在任何位置插入和删除元素都非常高效。
1.基本特性
(1)双向链表结构:每个元素都包含指向前驱和后继的指针
(2)非连续存储:元素分散存储在内存中,通过指针连接
(3)时间复杂度:
任意位置插入/删除:O(1)
随机访问:O(n)
遍历:O(n)
二、list常用操作
我这里就通过调试来带大家看一下每个函数的效果。
1.创建和构造
列举了一些list构造时的基础用法.
#include <iostream>
#include <list>
using namespace std;int main()
{list<int> l1; // 空listlist<int> l2(5); // 包含5个默认构造的元素(0)list<int> l3(5, 10); // 包含5个值为10的元素list<int> l4 = { 1, 2, 3 }; // 初始化列表list<int> l5(l4); // 拷贝构造list<int> l6(l5.begin(), l5.end()); // 通过迭代器范围构造return 0;
}

2.迭代器
由于list不支持随机访问,只能通过迭代器或front/back方法访问元素:
list<int> l = { 1, 2, 3, 4, 5 };cout << l.front()<<endl; // 第一个元素 (1)
cout << l.back()<<endl; // 最后一个元素 (5)// 遍历list
for (auto it = l.begin(); it != l.end(); ++it) {cout << *it << " ";
}
cout << endl;
// C++11起可用范围for循环
for (int val : l) {cout << val << " ";
}
return 0;

迭代器构造:

3.拷贝构造

4.clear()
效果:清空链表中所有数据。

5.size()
返回链表中节点的个数

6.push_back(const T& x)
在链表尾部插入值为x的节点。

7.push_front(const T& x)
在链表头部插入值为x的节点。

8.insert(iterator pos, const T& x)
在第pos个位置插入值为x的节点。

9.pop_back()
删除尾部元素

10.pop_front()
删除头部元素

11.erase(iterator pos)
删除第pos位置的元素


三、list的模拟实现
1.构造函数
首先我们可以通过STL库学习一下list的基本实现方法,然后自己根据SLTL库中的代码模拟实现一个list。
通过库中代码,我们需要先实现出list底层节点的模板以及迭代器所需要的模板,然后在构造函数。代码如下:
#define _CRT_SECURE_NO_WARNINGS 1
#include <assert.h>namespace lwf
{//创建模板结构体template<class T>struct list_node{list_node<T>* _next;list_node<T>* _prev;T _val;list_node(const T& val = T()):_next(nullptr), _prev(nullptr), _val(val){}};//创建模板结构体template<class T, class Ref, class Ptr>struct _list_iterator{typedef list_node<T> Node;typedef _list_iterator<T, Ref, Ptr> self;Node* _node;_list_iterator(Node* node):_node(node){}Ref operator*(){return _node->_val;}Ptr operator->(){return &_node->_val;}self& operator++(){_node = _node->_next;return *this;}self operator++(int){self tmp(*this);_node = _node->_next;return tmp;}self& operator--(){_node = _node->_prev;return *this;}self operator--(int){self tmp(*this);_node = _node->_prev;return tmp;}bool operator!=(const self& it){return _node != it._node;}bool operator==(const self& it){return _node == it._node;}};template<class T>class list{typedef list_node<T> Node;public:typedef _list_iterator<T, T&, T*> iterator;typedef _list_iterator<T, const T&, const T*> const_iterator;void empty_init(){_head = new Node;_head->_prev = _head;_head->_next = _head;_size = 0;}list(){empty_init();}list(const list<T>& It){empty_init();for (auto& e : It){push_back(e);}}private:Node* _head;size_t _size;};
}
2.迭代器
iterator begin(){//return iterator(_head->next);return _head->_next;}iterator end(){return _head;}const_iterator begin()const{//return iterator(_head->next);return _head->_next;}const_iterator end()const{return _head;}
3.拷贝构造
拷贝构造的实现就是将原有的list变量拷贝给被拷贝对象深拷贝。
list(const list<T>& It){empty_init();for (auto& e : It){push_back(e);}}void swap(list<T> It){std::swap(_head, It._head);std::swap(_size, It._size);}list<T>& operator=(list<T> It)//list& operator=(list<T> It) 这样写也可以{swap(It);return *this;}
4.clear()
通过迭代器来将list中元素逐个删除
void clear(){iterator it=begin();while (it != end()){it = erase(it);}_size = 0;}
5.size()
返回内部元素_size(_size一直是在统计list中元素的个数)即可。
size_t size(){return _size;}
6.insert(iterator pos, const T& x)
首先需要创建一个新节点,然后通过双链表结构的思路将节点插入所需要插入的位置,双链表在前面的博客中有实现过,需要的可自行查看。。
iterator insert(iterator pos, const T& x){Node* cur = pos._node;Node* prev = cur->_prev;Node* newnode = new Node(x);prev->_next = newnode;newnode->_prev = prev;cur->_prev = newnode;newnode->_next = cur;++_size;//解决迭代器失效问题return newnode;}
7.push_back(const T& x)
在list尾部插入x,此时我们这里可以巧妙的运用上面的insert(iterator pos, const T& x)函数来实现。
void push_back(const T& x){/*Node* tail = _head->_prev;Node* newnode = new Node(x);tail->_next = newnode;newnode->_prev = tail;newnode->_next = _head;_head->_prev = newnode;*/insert(end(), x);}
8.push_front(const T& x)
在list头部插入x,此时我们这里也可以巧妙的运用上面的insert(iterator pos, const T& x)函数来实现。
void push_front(const T& x){insert(begin(), x);}
9.erase(iterator pos)
删除list中pos位置的元素,这里的思路其实同双链表的删除操作一样,前面的博客中有实现过,需要的可自行查看。
iterator erase(iterator pos){assert(pos != end());Node* cur = pos._node;Node* prev = cur->_prev;Node* next = cur->_next;prev->_next = next;next->_prev = prev;delete cur;--_size;//解决迭代器失效问题return next;}
10.pop_back()
删除list的尾部,此时我们这里也可以巧妙的运用上面的erase(iterator pos)函数来实现。
void pop_back(){erase(--end());}
11.pop_front()
删除list的头部,此时我们这里也可以巧妙的运用上面的erase(iterator pos)函数来实现。
void pop_front(){erase(begin());}
12.析构函数
这里我们可以直接调动clear()函数来清除链表中的节点,然后释放private中的_head节点即可。
~list(){clear();delete _head;_head = nullptr;}
四、实现的整体代码。
这里是自我实现的所有代码的集合,需要的可自行拿取。
#pragma once#include<iostream>
using namespace std;
#include <assert.h>namespace lwf
{template<class T>struct list_node{list_node<T>* _next;list_node<T>* _prev;T _val;list_node(const T& val = T()):_next(nullptr), _prev(nullptr), _val(val){}};template<class T,class Ref,class Ptr>struct _list_iterator{typedef list_node<T> Node;typedef _list_iterator<T, Ref, Ptr> self;Node* _node;_list_iterator(Node* node):_node(node){}Ref operator*(){return _node->_val;}Ptr operator->(){return &_node->_val;}self& operator++(){_node = _node->_next;return *this;}self operator++(int){self tmp(*this);_node = _node->_next;return tmp;}self& operator--(){_node = _node->_prev;return *this;}self operator--(int){self tmp(*this);_node = _node->_prev;return tmp;}bool operator!=(const self& it){return _node != it._node;}bool operator==(const self& it){return _node == it._node;}};/*template<class T>struct _list_const_iterator{typedef list_node<T> Node;Node* _node;_list_const_iterator(Node* node):_node(node){}const T& operator*(){return _node->val;}_list_const_iterator<T>& operator++(){_node = _node->_next;return *this;}_list_const_iterator<T> operator++(int){_list_const_iterator<T> tmp(*this);_node = _node->_next;return tmp;}bool operator!=(const _list_const_iterator<T>& it)const{return _node != it._node;}bool operator==(const _list_const_iterator<T>& it)const{return _node == it._node;}};*/template<class T>class list{typedef list_node<T> Node;public:typedef _list_iterator<T, T&, T*> iterator;typedef _list_iterator<T, const T&, const T*> const_iterator;iterator begin(){//return iterator(_head->next);return _head->_next;}iterator end(){return _head;}const_iterator begin()const{//return iterator(_head->next);return _head->_next;}const_iterator end()const{return _head;}void empty_init(){_head = new Node;_head->_prev = _head;_head->_next = _head;_size = 0;}list(){empty_init();}list(const list<T>& It){empty_init();for (auto& e : It){push_back(e);}}void swap(list<T> It){std::swap(_head, It._head);std::swap(_size, It._size);}list<T>& operator=(list<T> It)//list& operator=(list<T> It) 这样写也可以{swap(It);return *this;}~list(){clear();delete _head;_head = nullptr;}void clear(){iterator it=begin();while (it != end()){it = erase(it);}_size = 0;}size_t size(){return _size;}void push_back(const T& x){/*Node* tail = _head->_prev;Node* newnode = new Node(x);tail->_next = newnode;newnode->_prev = tail;newnode->_next = _head;_head->_prev = newnode;*/insert(end(), x);}void push_front(const T& x){insert(begin(), x);}void pop_back(){erase(--end());}void pop_front(){erase(begin());}iterator insert(iterator pos, const T& x){Node* cur = pos._node;Node* prev = cur->_prev;Node* newnode = new Node(x);prev->_next = newnode;newnode->_prev = prev;cur->_prev = newnode;newnode->_next = cur;++_size;//解决迭代器失效问题return newnode;}iterator erase(iterator pos){assert(pos != end());Node* cur = pos._node;Node* prev = cur->_prev;Node* next = cur->_next;prev->_next = next;next->_prev = prev;delete cur;--_size;//解决迭代器失效问题return next;}private:Node* _head;size_t _size;};void Test_1(){list<int> It;It.push_back(1);It.push_back(2);It.push_back(3);It.push_back(4);It.push_front(5);It.push_front(6);It.push_front(7);It.push_front(8);for (auto& e : It){cout << e << " ";}cout << endl;It.pop_back();It.pop_front();for (auto& e : It){cout << e << " ";}cout << endl;}void Test_2(){list<int> It;It.push_back(1);It.push_back(2);It.push_back(3);It.push_back(4);It.push_front(5);It.push_front(6);It.push_front(7);It.push_front(8);for (auto& e : It){cout << e << " ";}cout << endl;It.pop_back();It.pop_front();for (auto& e : It){cout << e << " ";}cout << endl;It.clear();It.push_front(50);It.push_front(60);It.push_front(70);It.push_front(80);for (auto& e : It){cout << e << " ";}cout << endl;cout << It.size() << endl;}void Test_3(){list<int> lt;lt.push_back(1);lt.push_back(2);lt.push_back(3);lt.push_back(4);for (auto e : lt){cout << e << " ";}cout << endl;list<int> lt1(lt);for (auto e : lt1){cout << e << " ";}cout << endl;list<int> lt2;lt2.push_back(10);lt2.push_back(20);lt2.push_back(30);lt2.push_back(40);for (auto e : lt2){cout << e << " ";}cout << endl;lt1 = lt2;for (auto e : lt1){cout << e << " ";}cout << endl;}
}
五、感言
家人们创作不易,在这里感谢各位大佬和友友们的支持,如果各位有所收获,不介意的话给我点个赞再走吧,感谢大家!

相关文章:
C++_STL之list篇
一、list的介绍 std::list是C标准模板库(STL)中的一个双向链表容器。与vector和deque不同,list不支持随机访问,但它在任何位置插入和删除元素都非常高效。 1.基本特性 (1)双向链表结构:每个元素都包含指向前驱和后继的指针 (2)非连续存储&…...
Go中的逃逸分析
什么是逃逸? 逃逸是指一个变量本来应该分配在栈(stack)上,但由于某些原因,最终被分配到了堆(heap)上。 类比: 栈就像一个临时的快餐盒,用来存放短期使用的数据。堆就像…...
Spring 声明式事务 万字详解(通俗易懂)
目录 Δ前言 一、声明式事务快速入门 1.为什么需要声明式事务? 2.定义: 3.应用实例: 二、声明式事务的传播机制 1.引出问题: 2.传播机制分类: 3.应用实例: 三、声明式事务的隔离机制 1.四种隔离级别&…...
MySQL 当中的锁
MySQL 当中的锁 文章目录 MySQL 当中的锁MySQL 中有哪些主要类型的锁?请简要说明MySQL 的全局锁有什么用?MySQL 的表级锁有哪些?作用是什么?元数据锁(MetaData Lock,MDL)意向锁(Inte…...
fyrox 2D和3D游戏的制作
目录 fyrox介绍 1. 核心特性 1.1 高性能渲染 1.2 跨平台支持 1.3 物理引擎集成 1.4 脚本系统 1.5 场景管理 2. 架构设计 2.1 渲染器 2.2 资源管理器 2.3 输入系统 2.4 音频引擎 2.5 网络模块 3. 使用场景 3.1 2D游戏 3.2 3D游戏 3.3 模拟与教育应用 4. 在游戏…...
[Linux]基础IO
基础IO C文件IO相关操作磁盘文件与内存文件inode(index node)硬链接与软连接硬链接软连接总结 动静态库静态库动态库总结 C文件IO相关操作 当前路径:进程运行的时候,所处的路径叫做当前路径 打开文件的时候,一定是进…...
力扣刷题-热题100题-第27题(c++、python)
21. 合并两个有序链表 - 力扣(LeetCode)https://leetcode.cn/problems/merge-two-sorted-lists/description/?envTypestudy-plan-v2&envIdtop-100-liked 常规法 创建一个新链表,遍历list1与list2,将新链表指向list1与list2…...
Vue3 其它API Teleport 传送门
Vue3 其它API Teleport 传送门 在定义一个模态框时,父组件的filter属性会影响子组件的position属性,导致模态框定位错误使用Teleport解决这个问题把模态框代码传送到body标签下...
windows下安装sublime
sublime4 alpha 4098 版本 下载 可以根据待破解的版本选择下载 https://www.sublimetext.com/dev crack alpha4098 的licence 在----- BEGIN LICENSE ----- TwitterInc 200 User License EA7E-890007 1D77F72E 390CDD93 4DCBA022 FAF60790 61AA12C0 A37081C5 D0316412 4584D…...
golang 的strconv包常用方法
目录 1. 字符串与整数的转换 2. 字符串与浮点数的转换 3. 布尔值的转换 4. 字符串的转义 5. 补充:rune 类型的使用 方法功能详解 代码示例: 1. 字符串与整数的转换 方法名称功能描述示例Atoi将字符串转换为十进制整数。strconv.Atoi("123&q…...
ComplexE的代码注释
目录 dataloader.pymodel.pyrun.py 先安装软件,配置环境,搞了一周。再看代码写注释搞了一周。中间隔了一周。再安装环境跑代码又一周。最后结果是没结果。自己电脑内存带不动。还不想配电脑,又不会用GPU服务器。哭死哭死。心态崩了。直接发吧…...
vector<int> 的用法
vector<int> 是 C 标准模板库(STL)中的一个容器,用于存储动态大小的整数序列。以下是它的主要用法: 基本操作 1. 创建和初始化 #include <vector> using namespace std;vector<int> v1; // 空vector vector<int>…...
Java高级JVM知识点记录,内存结构,垃圾回收,类文件结构,类加载器
JVM是Java高级部分,深入理解程序的运行及原理,面试中也问的比较多。 JVM是Java程序运行的虚拟机环境,实现了“一次编写,到处运行”。它负责将字节码解释或编译为机器码,管理内存和资源,并提供运行时环境&a…...
名言警句1
1、嫉妒是欲望的衍生,而欲望则是成长的驱动,说到底每个人都是为了成长,为了不居人后,在成长的过程中,我们可以让欲望枝繁叶茂,但不能让嫉妒开花结果 2、人生无法奢求更多,我们有健康的身体&…...
【STL】queue
q u e u e queue queue 是一种容器适配器,设计为先进先出( F i r s t I n F i r s t O u t , F I F O First\ In\ First\ Out,\ FIFO First In First Out, FIFO)的数据结构,有两个出口,将元素推入队列的操作称为 p u …...
QXmpp入门
QXmpp 是一个基于 Qt 的 XMPP (Jabber) 协议实现库,用于开发即时通讯(IM)、聊天应用和实时协作系统。它支持客户端和服务端开发,提供完整的 XMPP 核心功能扩展。 1. 核心功能 XMPP 核心协议支持 支持 RFC 6120 (XMPP Core) 和 RFC 6121 (XMPP IM) 基础功能:认证、在线状态…...
使用cursor为代码添加注释
1. add-comments.md英文 You are tasked with adding comments to a piece of code to make it more understandable for AI systems or human developers. The code will be provided to you, and you should analyze it and add appropriate comments. To add comments to …...
20250330-傅里叶级数专题之离散时间傅里叶变换(4/6)
4. 傅里叶级数专题之离散时间傅里叶变换 20250328-傅里叶级数专题之数学基础(0/6)-CSDN博客20250330-傅里叶级数专题之傅里叶级数(1/6)-CSDN博客20250330-傅里叶级数专题之傅里叶变换(2/6)-CSDN博客20250330-傅里叶级数专题之离散傅里叶级数(3/6)-CSDN博客20250330-傅里叶级数专…...
漏洞挖掘---迅饶科技X2Modbus网关-GetUser信息泄露漏洞
一、迅饶科技 X2Modbus 网关 迅饶科技 X2Modbus 网关是功能强大的协议转换利器。“X” 代表多种不同通信协议,能将近 200 种协议同时转为 Modbus RTU 和 TCP 服务器 。支持 PC、手机端等访问监控,可解决组态软件连接不常见控制设备难题,广泛…...
Java进阶——位运算
位运算直接操作二进制位,在处理底层数据、加密算法、图像处理等领域具有高效性能和效率。本文将深入探讨Java中的位运算。 本文目录 一、位运算简介1. 与运算2. 或运算异或运算取反运算左移运算右移运算无符号右移运算 二、位运算的实际应用1. 权限管理2. 交换两个变…...
golang strings包常用方法
方法名称功能描述示例strings.Join将字符串切片中的元素连接成一个字符串,使用指定的分隔符。strings.Join([]string{"hello", "world"}, " ")strings.HasPrefix检查字符串是否以指定的前缀开头。strings.HasPrefix("hello"…...
网络安全之前端学习(css篇2)
那么今天我们继续来学习css,预计这一章跟完后,下一章就是终章。然后就会开始js的学习。那么话不多说,我们开始吧。 字体属性 之前讲到了css可以改变字体属性,那么这里来详细讲一讲。 1.1字体颜色 之前讲到了对于字体改变颜色食…...
PS底纹教程
1.ctrlshiftU 去色 2.新建纯色层 颜色中性灰;转换为智能对象 3.纯色层打开滤镜(滤镜库); 素描下找到半调图案,数值调成大小5对比1; 再新建一层,素描下找到撕边,对比拉到1&#x…...
NX/UG二次开发—CAM获取加工操作的最低Z深度值的方法
网上已经有些大佬给出了解决方案,但是基本有两种,一种内部函数,另外一种就是导出程序的刀轨文件找坐标计算。使用内部函数进行操作,可以自己学习,不做解释。下面只是针对第二种进行说明,参考胡君老师的教程…...
解决pyinstaller GUI打包时无法打包图片问题
当我们的python GuI在开发时。经常会用到图片作为背景,但是在打包后再启动GUI后却发现:原先调试时好端端的背景图片竟然不翼而飞或者直接报错。这说明图片没有被pyinstaller一起打包…… 要解决这个问题很简单,就是更改图片的存储方式。 tk…...
蓝桥杯真题------R格式(高精度乘法,高精度加法)
对于高精度乘法和加法的同学可以学学这几个题 高精度乘法 高精度加法 文章目录 题意分析部分解全解 后言 题意 给出一个整数和一个浮点数,求2的整数次幂和这个浮点数相乘的结果最后四舍五入。、 分析 我们可以发现,n的范围是1000,2的1000次方非常大&am…...
Nginx — Nginx安装证书模块(配置HTTPS和TCPS)
一、安装和编译证书模块 [rootmaster nginx]# wget https://nginx.org/download/nginx-1.25.3.tar.gz [rootmaster nginx]# tar -zxvf nginx-1.25.3.tar.gz [rootmaster nginx]# cd nginx-1.25.3 [rootmaster nginx]# ./configure --prefix/usr/local/nginx --with-http_stub_…...
回调后门基础
回调后门概述 回调后门(Reverse Shell)是一种常见的攻击方式,攻击者通过受害主机主动连接到远程服务器(攻击者控制的机器),从而获得远程控制权限。 工作原理 受害者主机 运行一个恶意代码,尝…...
深度学习 Deep Learning 第13章 线性因子模型
深度学习 Deep Learning 第13章 线性因子模型 内容概要 本章深入探讨了线性因子模型,这是一类基于潜在变量的概率模型,用于描述数据的生成过程。这些模型通过简单的线性解码器和噪声项捕捉数据的复杂结构,广泛应用于信号分离、特征提取和数…...
【个人笔记】用户注册登录思路及实现 springboot+mybatis+redis
基本思路 获取验证码接口 验证码操作用了com.pig4cloud.plugin的captcha-core这个库。 AccountControl的"/checkCode"接口代码,通过ArithmeticCaptcha生成一张验证码图片,通过text()函数得到验证码的答案保存到变量code,然后把图…...

