STL——list
一、list介绍及使用
1. list文档介绍
(1)list是可以在常数范围内,在任意位置进行插入、删除的序列式容器,并且该容器可以前后双向迭代。
(2)list的底层是带头结点的双向循环链表,其中每个元素存储在互不相关的独立节点中,在节点中通过指针指向其前一个元素和后一个元素。
(3)list和forward_list非常相似。最主要的不同在于forward_list是单链表,只能朝前迭代。
(4)与其他的序列式容器相比(array、vector、deque),list通常在任意位置的插入、删除元素的执行效率更高。
(5)与其他序列式容器相比,list和forward_list最大的缺陷是不支持任意位置的随机访问。
2. list常用接口介绍
2.1 list的构造
2.2 list iterator的使用
2.3 list capacity
2.4 list 元素访问
2.5 list 元素修改
3. list迭代器失效问题
3.1迭代器失效
迭代器失效,即迭代器所指向的节点无效,在list中即该节点被删除了。
因为list的底层结构为带头节点的双向循环链表,因此在list中插入元素是不会导致list迭代器失效,只有在删除时才会失效,并且失效的只是指向被删除节点的迭代器,其他迭代器不会受到影响。
3.2 list可能导致迭代器失效的操作
pop_back、pop_front、erase、resize、assign……
3.3解决方法
在所有可能导致迭代器失效的操作之后,在使用迭代器前对迭代器进行重新赋值。
二、list与vector的区别★
注意:
空间利用率上,只是绝大多数情况下vector比list高,因为list每个节点多了两个指针域,但并不绝对。
三、模拟实现list
1.实现接口
1.1私有成员
void CreateHead();//创建头节点
Node* _head;
1.2默认成员
//默认构造函数
list();
//n个value构造
list(size_t n, const T& value = T());
template<class Iterator>
//区间构造
list(Iterator first, Iterator last);
//拷贝构造
list(const list<T>& L);
//赋值运算符重载
list<T>& operator=(list<T> L)//析构函数
~list();
1.3迭代器
注意:
list迭代器不能使用原生态的指针,因为list空间不连续,不能对指针进行算数运算。所以需要自己模拟封装迭代器对应类
template<class T, class Ref, class Ptr>
struct ListIterator;
template<class Iterator>
struct ListReverseIterator;iterator begin();
iterator end();
const_iterator cbegin() const;
const_iterator cend() const;
reverse_iterator rbegin();
reverse_iterator rend();
const_reverse_iterator crbegin() const;
const_reverse_iterator crend() const;
1.4容量
size_t size() const ;
bool empty() ;
void resize(size_t newSize, const T& value = T()) ;
1.5元素访问
T& front();
const T& front() const;
T& back();
const T& back() const ;
1.6元素修改
void push_front(const T& value);
void pop_front();
void push_back(const T& value) ;
void pop_back();
iterator insert(iterator it, const T& value);
iterator erase(iterator it);
void clear();
void swap(list<T>& L) ;
2.代码实现
#include <iostream>
using namespace std;namespace MyList {//链表节点template<class T>struct ListNode {ListNode<T>* _next;ListNode<T>* _prev;T _val;ListNode(const T& value = T()): _next(nullptr), _prev(nullptr), _val(value){}};//注意:list迭代器不能使用原生态的指针//因为list空间不连续,不能对指针进行算数运算//模拟封装迭代器类template<class T, class Ref, class Ptr>struct ListIterator {typedef ListNode<T> Node;typedef Ref ItRef;typedef Ptr ItPtr;typedef ListIterator<T, Ref, Ptr> Self;public://构造ListIterator(Node* node = nullptr):_node(node){}/*----------实现类似指针的操作----------*/Ref operator*() {return _node->_val;}Ptr operator->() {return &(operator*());}/*----------实现"++""--"----------*/Self& operator++() {_node = _node->_next;return *this;}Self operator++(int) {Self temp(*this);_node = _node->_next;return temp;}Self& operator--() {_node = _node->_prev;return *this;}Self& operator--(int) {Self temp(*this);_node = _node->_prev;return temp;}/*----------实现比较----------*/bool operator!=(const Self& s) const {return _node != s._node;}bool operator==(const Self& s) const {return _node == s._node;}public:Node* _node;};//模拟封装反向迭代器:内部封装正向迭代器即可template<class Iterator>struct ListReverseIterator {//因为静态成员变量也可以通过类名::静态成员名称的方式进行访问//直接写会编译报错,编译器不确定ItRef、ItPtr是静态成员变量还是类型//所以需要显示告诉编译器是typenametypedef typename Iterator::ItRef Ref;typedef typename Iterator::ItPtr Ptr;typedef ListReverseIterator<Iterator> Self;public:ListReverseIterator(Iterator it):_it(it){}Ref operator*() {Iterator temp(_it);--temp;return *temp;}Ptr operator->() {return &(*operator*());}Self& operator++() {--_it;return *this;}Self operator++(int) {Self temp(*this);--_it;return temp;}Self& operator--() {++_it;return *this;}Self operator--(int) {Self temp(*this);++_it;return temp;}bool operator!=(const Self& rit) const {return _it != rit._it;}bool operator==(const Self& rit) const {return _it == rit._it;}public:Iterator _it;//正向迭代器};/*=========================================================================================*/template<class T>class list {typedef ListNode<T> Node;public:typedef ListIterator<T, T&, T*> iterator;typedef ListIterator<T, const T&, const T*> const_iterator;typedef ListReverseIterator<iterator> reverse_iterator;typedef ListReverseIterator<const_iterator> const_reverse_iterator;public:/*----------默认成员----------*///默认构造函数list() {CreateHead();}//n个value构造list(int n, const T& value = T()) {CreateHead();for (int i = 0; i < n; ++i) { push_back(value); }}template<class Iterator>//区间构造list(Iterator first, Iterator last) {CreateHead();while (first != last) {push_back(*first);++first;}}//拷贝构造list(const list<T>& L) {CreateHead();auto it = L.cbegin();while (it != L.cend()) {push_back(*it);++it;}}//赋值运算符重载list<T>& operator=(list<T> L) {this->swap(L);return *this;}//析构函数~list() {clear();delete _head;_head = nullptr;}/*----------迭代器----------*/iterator begin() {return iterator(_head->_next);}iterator end() {return iterator(_head);}const_iterator cbegin() const {return const_iterator(_head->_next);}const_iterator cend() const {return const_iterator(_head);}reverse_iterator rbegin() {return reverse_iterator(end());}reverse_iterator rend() {return reverse_iterator(begin());}const_reverse_iterator crbegin() const {return const_reverse_iterator(cend());}const_reverse_iterator crend() const {return const_reverse_iterator(cbegin());}/*----------容量----------*/size_t size() const {Node* cur = _head->_next;size_t count = 0;while (cur != _head) {++count;cur = cur->_next;}return count;}bool empty() {return _head->_next == _head;}void resize(size_t newSize, const T& value = T()) {size_t oldSize = size();if (newSize < oldSize) {for (size_t i = oldSize; i > newSize; --i) { pop_back(); }}else {for (size_t i = oldSize; i < newSize; ++i) { push_back(value); }}}/*----------元素访问----------*/T& front() {return *begin();}const T& front() const {return *cbegin();}T& back() {return *(--end);}const T& back() const {return *(--cend);}/*----------元素修改----------*/void push_front(const T& value) {insert(begin(), value);}void pop_front() {erase(begin());}void push_back(const T& value) {insert(end(), value);}void pop_back() {erase(end()--);}iterator insert(iterator it, const T& value) {Node* pos = it._node;//插入方式,将新节点连接进去,再断开原链表Node* temp = new Node(value);//(1)连接temp->_next = pos;temp->_prev = pos->_prev;//(2)断开temp->_prev->_next = temp;temp->_next->_prev = temp;return iterator(temp);}iterator erase(iterator it) {if (it == end()) return end();Node* pos = it._node;Node* ret = pos->_next;pos->_prev->_next = pos->_next;pos->_next->_prev = pos->_prev;delete pos;return iterator(ret);}void clear() {auto it = begin();while (it != end()) {it = erase(it);//记得重新赋值,防止迭代器失效}}void swap(list<T>& L) {std::swap(_head, L._head);}/*----------私有成员----------*/private:void CreateHead() {//创建头节点_head = new Node();_head->_next = _head;_head->_prev = _head;}Node* _head;};
}
相关文章:

STL——list
一、list介绍及使用 1. list文档介绍 (1)list是可以在常数范围内,在任意位置进行插入、删除的序列式容器,并且该容器可以前后双向迭代。 (2)list的底层是带头结点的双向循环链表,其中每个元素…...

实战打靶集锦-004-My-Cmsms
**写在前面:**记录一次艰难曲折的打靶经历。 目录1. 主机发现2. 端口扫描3. 服务枚举4. 服务探查4.1 WEB服务探查4.1.1 浏览器访问4.1.2 目录枚举4.1.3 控制台探查4.1.4 其他目录探查4.2 阶段小结5. 公共EXP搜索5.1 CMS搜索5.2 Apache搜索5.3 PHP搜索5.4 MySQL搜索5…...
c++代码实现我的世界(14)
c代码实现我的世界14|生成地貌兼工作台1前言的前言~前言生成地貌函数结构体struct dimao根据比例生成地貌工作台函数准备的东西写在最后前言的前言~ 实在对不起大家,有挺长时间没更新了。 前言 今天我们将写生成地形的函数与工作台前传的代码; 注&…...

RMQ--区间最值问题(在更)
RMQ(Range Minimum/Maximum Query)RMQ解决的问题ST算法 O(nlogn)线段树例题数列区间最大值最敏捷的机器人天才的记忆Frequent values总结(ST和线段树对比)RMQ解决的问题 RMQ是一个解决多个区间最值查询的算法,即区间最值查询&…...

一篇文章搞懂Cookie
目录 1 什么是Cookie 2 创建Cookie 3 浏览器查看Cookie 3.1 浏览器查看Cookie的第一种方式 3.2 浏览器查看Cookie的第二种方式 4 获取Cookie 5 修改Cookie 6 Cookie编码与解码 6.1 创建带中文Cookie 6.2 读取带中文Cookie 6.3 获取中文Cookie请求效果 6.4 解决创建和…...
深入解读.NET MAUI音乐播放器项目(二):播放内核
播放控制服务 IMusicControlService: 播放控制类,用于当前平台播放器对象的操作,对当前所播放曲目的暂停/播放,下一首/上一首,快进快退(寻迹),随机、单曲模式等功能的控制。 播放控制类包含一…...

4.SpringWeb
一、创建项目LomBok:辅助开发工具,减少代码编写Spring Web:带上Spring MVC,可以做Web开发了Thymleaf: Web开发末班引擎(不常用)创建好,如下:static/ 放置静态资源的根目录templates/ 放置模板文件的根目录 二、资源配置…...

C++中的枚举与位域
枚举在传统 C中,枚举类型并非类型安全,枚举类型会被视作整数,则会让两种完全不同的枚举类型可以进行直接的比较(虽然编译器给出了检查,但并非所有),甚至同一个命名空间中的不同枚举类型的枚举值…...
第19章 MongoDB Limit与Skip方法教程
第19章 MongoDB Limit与Skip方法教程 MongoDB Limit() 方法 如果仁兄需要在MongoDB中读取指定数量的数据记录,可以使用MongoDB的Limit方法,limit()方法接受一个数字参数,该参数指定从MongoDB中读取的记录条数。 语法 limit()方法基本语法请…...
进程间通信——消息队列
多线程 进程间通信——消息队列 消息队列——发送 测试代码 #include <sys/types.h> #include <sys/msg.h> #include <sys/ipc.h>#include <stdlib.h> #include <stdio.h> #include <string.h>#define MAX_BUF_SIZE 255struct msgtype {…...

OpenMMLab 实战营打卡 - 第 7 课
OpenMMLab MMSegmentation内容概要MMSegmentation统一超参MMSegmentation 的项目结构分割模型的模块化设计分割模型的配置文件主干网络的配置ResNet v1c主解码头的配置辅助解码头的配置数据集配置数据处理流水线常用训练策略参考资料内容概要 • MMSegmentation 项目概述 • M…...

MAC Boook打印长图
有时老师给留的作业是一张长图,直接打印或者通过把图放入word打印都不能实现把长页分成多页进行打印。通过网上找到思路可以通过EXCEL实现将长图分成多页打印。 测试版本 macos:ventura 13.1 office 365 注:同样适用windows版本的excel 第…...

web3:区块链共识机制系列-POS(Proof of Stake)股权证明算法
web3相关学习一并收录至该博客:web3学习博客目录大全 前情衔接:web3:区块链常见的几大共识机制及优缺点 目录前言算法公式与原理算法公式运作原理以Peer Coin为例缺陷优点缺点特点分类发展历程casper协议1.什么是无成本利益关系问题2.引入casper协议解决…...
Linux fork()系统调用流程解析
1. fork()函数介绍(百度百科) fork系统调用用于创建一个新进程,称为子进程,它与进程(称为系统调用fork的进程)同时运行,此进程称为父进程。创建新的子进程后,两个进程将执行fork&…...

自定义软件帮助文档(qt assistant实现)
网上搜了一下,软件的帮助文档,三个都可以:https://github.com/zealdocs/zeal,https://zealdocs.org/,看看这个博客说的 https://blog.csdn.net/libaineu2004/article/details/125028913,这个也是开源的&…...
ESP32设备驱动-GPIO外部中断
GPIO外部中断 文章目录 GPIO外部中断1、GPIO中断介绍2、GPIO中断使用步骤3、软件准备4、硬件准备5、代码实现在前面的文章 ESP32设备驱动-GPIO数字输入与输出中介绍如何对GPIO进行控制操作。本文将在该基础上使用GPIO中断进一步优化按键输入。即演示如何使用GPIO中断。 1、GPI…...

【安全】nginx反向代理+负载均衡上传webshel
Nginx负载均衡下上传webshell 什么是反向代理? 正向代理就是代替客户端进行各种服务的访问以及获取;那么反向代理自然就是代替服务器进行事务处理,就是此时的代理服务器负责将用户的各项请求做一个汇总、分类,将其分发到不同的服务…...
华为OD机试 - 单词接龙(Python)| 真题,思路,知识点
单词接龙 题目 单词接龙的规则是: 可用于接龙的单词,首字母必须要与前一个单词的尾字母相同; 当存在多个首字母相同的单词时,取长度最长的单词; 如果长度也相等,则取字典序最小的单词; 已经参与接龙的单词不能重复使用; 现给定一组全部由小写字母组成的单词数组, 并指…...

[ 系统安全篇 ] window 命令禁用用户及解禁方法
🍬 博主介绍 👨🎓 博主介绍:大家好,我是 _PowerShell ,很高兴认识大家~ ✨主攻领域:【渗透领域】【数据通信】 【通讯安全】 【web安全】【面试分析】 🎉点赞➕评论➕收藏 养成习…...

Https 协议超强讲解(二)
浏览器是如何确保 CA 证书的合法性? 1. 证书包含什么信息? 颁发机构信息 公钥 公司信息 域名 有效期 指纹 …… 2. 证书的合法性依据是什么? 首先,权威机构是要有认证的,不是随便一个机构都有资格颁发证书&am…...
【算法训练营Day07】字符串part1
文章目录 反转字符串反转字符串II替换数字 反转字符串 题目链接:344. 反转字符串 双指针法,两个指针的元素直接调转即可 class Solution {public void reverseString(char[] s) {int head 0;int end s.length - 1;while(head < end) {char temp …...
Python ROS2【机器人中间件框架】 简介
销量过万TEEIS德国护膝夏天用薄款 优惠券冠生园 百花蜂蜜428g 挤压瓶纯蜂蜜巨奇严选 鞋子除臭剂360ml 多芬身体磨砂膏280g健70%-75%酒精消毒棉片湿巾1418cm 80片/袋3袋大包清洁食品用消毒 优惠券AIMORNY52朵红玫瑰永生香皂花同城配送非鲜花七夕情人节生日礼物送女友 热卖妙洁棉…...
Caliper 配置文件解析:fisco-bcos.json
config.yaml 文件 config.yaml 是 Caliper 的主配置文件,通常包含以下内容: test:name: fisco-bcos-test # 测试名称description: Performance test of FISCO-BCOS # 测试描述workers:type: local # 工作进程类型number: 5 # 工作进程数量monitor:type: - docker- pro…...
在 Spring Boot 项目里,MYSQL中json类型字段使用
前言: 因为程序特殊需求导致,需要mysql数据库存储json类型数据,因此记录一下使用流程 1.java实体中新增字段 private List<User> users 2.增加mybatis-plus注解 TableField(typeHandler FastjsonTypeHandler.class) private Lis…...

数据结构:递归的种类(Types of Recursion)
目录 尾递归(Tail Recursion) 什么是 Loop(循环)? 复杂度分析 头递归(Head Recursion) 树形递归(Tree Recursion) 线性递归(Linear Recursion)…...

C++实现分布式网络通信框架RPC(2)——rpc发布端
有了上篇文章的项目的基本知识的了解,现在我们就开始构建项目。 目录 一、构建工程目录 二、本地服务发布成RPC服务 2.1理解RPC发布 2.2实现 三、Mprpc框架的基础类设计 3.1框架的初始化类 MprpcApplication 代码实现 3.2读取配置文件类 MprpcConfig 代码实现…...
书籍“之“字形打印矩阵(8)0609
题目 给定一个矩阵matrix,按照"之"字形的方式打印这个矩阵,例如: 1 2 3 4 5 6 7 8 9 10 11 12 ”之“字形打印的结果为:1,…...

Canal环境搭建并实现和ES数据同步
作者:田超凡 日期:2025年6月7日 Canal安装,启动端口11111、8082: 安装canal-deployer服务端: https://github.com/alibaba/canal/releases/1.1.7/canal.deployer-1.1.7.tar.gz cd /opt/homebrew/etc mkdir canal…...
深入解析 ReentrantLock:原理、公平锁与非公平锁的较量
ReentrantLock 是 Java 中 java.util.concurrent.locks 包下的一个重要类,用于实现线程同步,支持可重入性,并且可以选择公平锁或非公平锁的实现方式。下面将详细介绍 ReentrantLock 的实现原理以及公平锁和非公平锁的区别。 ReentrantLock 实现原理 基本架构 ReentrantLo…...

Spring是如何实现无代理对象的循环依赖
无代理对象的循环依赖 什么是循环依赖解决方案实现方式测试验证 引入代理对象的影响创建代理对象问题分析 源码见:mini-spring 什么是循环依赖 循环依赖是指在对象创建过程中,两个或多个对象相互依赖,导致创建过程陷入死循环。以下通过一个简…...