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

初识c++——list

一、list

1、list结构

c++中list为双向带头循环列表:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

二、list接口

1、构造

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

using namespace std;
#include<iostream>
#include<list>
#include<vector>
int main()
{list<int> lt; //构造空的listlist<int> lt1(10, 1); //构造的list中包含n个值为val的元素for (auto& it : lt1){cout << it;}list<int> lt2 = lt1;//拷贝构造函数vector<int>vr(10, 2);list<int> lt3(vr.begin(), vr.end());for (auto& it : lt3){cout << it;}return 0;
}

2、迭代器

注:c++的迭代器不支持+,-操作符

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

1. begin与end为正向迭代器,对迭代器执行++操作,迭代器向后移动

2. rbegin(end)与rend(begin)为反向迭代器,对迭代器执行++操作,迭代器向前移动

3、空间

在这里插入图片描述

using namespace std;
#include<iostream>
#include<list>
#include<vector>
int main()
{list<int> lt; //构造空的listlist<int> lt1(10, 1); //构造的list中包含n个值为val的元素for (auto& it : lt1){cout << it;}list<int> lt2 = lt1;//拷贝构造函数vector<int>vr(10, 2);list<int> lt3(vr.begin(), vr.end());for (auto& it : lt3){cout << it;}if (!lt3.empty()){cout << lt3.size();}return 0;
}

4、节点访问

在这里插入图片描述

using namespace std;
#include<iostream>
#include<list>
#include<vector>
int main()
{list<int> lt; //构造空的listlist<int> lt1(10, 1); //构造的list中包含n个值为val的元素for (auto& it : lt1){cout << it;}list<int> lt2 = lt1;//拷贝构造函数vector<int>vr(10, 2);list<int> lt3(vr.begin(), vr.end());for (auto& it : lt3){cout << it;}cout << endl;if (!lt3.empty()){cout << lt3.size() << lt3.front() << lt3.back();}return 0;
}

5、修改元素

在这里插入图片描述

using namespace std;
#include<iostream>
#include<list>
#include<vector>
int main()
{list<int> lt1(10, 1); list<int> lt2(10, 2);lt1.push_back(3);//尾插lt1.pop_back();//尾删lt1.push_front(3);//头插lt1.pop_front();//头删lt1.insert(lt1.begin(), 3);//在list position 位置中插入值为val的元素lt1.erase(lt1.begin()); //删除list position位置的元素lt1.swap(lt2);//交换两个list中的元素for (auto& it : lt1){cout << it;}lt1.clear();//清空list中的有效元素for (auto& it : lt1){cout << it;}return 0;
}

三、迭代器失效

我们在平时可将迭代器暂时理解成类似于指针,迭代器失效即迭代器所指向的节点的无

效,即该节点被删除了。因为list的底层结构为带头结点的双向循环链表,因此在list中进行插入

时是不会导致list的迭代器失效的,只有在删除时才会失效,并且失效的只是指向被删除节点的迭

代器,其他迭代器不会受到影响。

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);}
}

四、模拟实现

1、构造和析构

void CreateHead()
{_pHead = new Node;_pHead->_pNext = _pHead->_pPre = _pHead;_list_size = 0;
}
list()
{CreateHead();
}list(int n, const T& value = T())
{for (size_t i = 0; i < n; i++){push_back(value);}
}template <class Iterator>
list(Iterator first, Iterator last)
{auto it = first;while (it!=last){push_back(*it);it++;}
}list(const list<T>& l)
{CreateHead();for (auto& e : lt){push_back(e);}
}void swap(list<T>& l)
{std::swap(_pHead, l._pHead);std::swap(_list_size, l._list_size);
}
list<T>& operator=(const list<T> l)
{swap(lt);return *this;
}~list()
{clear();delete _pHead;_pHead = nullptr;
}

2、迭代器

由于list的储存空间不是连续的,所以我们要单独实现++/–等操作,所以我们直接放在一个类中去实现它(但是我们还是用节点指针去实现它,所以成员函数还是节点指针),这里以const_iterator为例子

template<class T>
struct list_const_iterator
{typedef list_node<T> Node;typedef list_const_iterator<T> Self;Node* _node;list_const_iterator(Node* node):_node(node){}const T& operator*(){return _node->_data;}const T* operator->()//这里主要是为了有成员变量也是类的情况{return &_node->_data;}Self& operator++(){_node = _node->_next;return *this;}Self& operator--(){_node = _node->_prev;return *this;}Self operator++(int){Self tmp(*this);_node = _node->_next;return tmp;}Self& operator--(int){Self tmp(*this);_node = _node->_prev;return tmp;}bool operator!=(const Self& s) const{return _node != s._node;}bool operator==(const Self& s) const{return _node == s._node;}
};

但是这样写太过麻烦,我们看库里面是如何实现的:

在这里插入图片描述

template<class T, class Ref, class Ptr>
struct ListIterator
{typedef ListNode<T>* PNode;typedef ListIterator<T, Ref, Ptr> Self;
public:ListIterator(PNode pNode = nullptr):_node(pNode){}T& operator*(){return _node->_val;}T* operator->(){return &_node->_val;}Self& operator++() {_node = _node->_pNext;return *this;}Self& operator++(int){Self tmp(*this);_node = _node->_pNext;return tmp;}Self& operator--(){_node = _node->_pPre;return *this;}Self& operator--(int){Self tmp(*this);_node = _node->_pPre;return tmp;}bool operator!=(const Self& l) const{return _node != l._node;}bool operator==(const Self& l) const{return _node == l._node;}PNode _node;
};iterator begin(){return _pHead->_pNext;//这走隐式类型转化}iterator end(){return _pHead;}const_iterator begin() const{return _pHead->_pNext;}const_iterator end() const{return _pHead;}

这里画个图帮大家理解一下:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

3、空间

size_t size()const
{return _list_size;
}
bool empty()const
{return _list_size == 0;
}

4、数据操作

// List Access
T& front()
{return _pHead->_pNext->_val;
}
const T& front()const
{return _pHead->_pNext->_val;
}
T& back()
{return _pHead->_pPre->_val;
}
const T& back()const
{return _pHead->_pPre->_val;
}// List Modifyvoid push_back(const T& val){insert(begin(), val);}void pop_back(){erase(--end());}void push_front(const T& val){insert(end(), val);}void pop_front(){erase(begin());}// 在pos位置前插入值为val的节点iterator insert(iterator pos, const T& val){Node* node = new Node(val);Node* pre = pos._node->_pPre;pre->_pNext = node;pos._node->_pPre = node;node->_pNext = pos._node;node->_pPre = pre;++_list_size;return node;}// 删除pos位置的节点,返回该节点的下一个位置iterator erase(iterator pos){assert(pos != end());//不能释放哨兵位头节点Node* pre = pos._node->_pPre;Node* next = pos._node->_pNext;pre->_pNext = next;next->_pPre = pre;delete pos._node;--_list_size;return next;}void clear(){auto it = begin();while (it != end()){it = erase(it);}_list_size = 0;}

这里唯一要注意不能删除哨兵位的节点,这样会导致无法访问该list(begin,end都和l哨兵位有关),所以erase不能删除end的节点(end指向的就是哨兵位节点)

5、总文件

#pragma once
#include<iostream>
#include<assert.h>
using namespace std;
namespace lt
{// List的节点类template<class T>struct ListNode{ListNode(const T& val = T()):_val(val),_pPre(nullptr),_pNext(nullptr){}ListNode<T>* _pPre;ListNode<T>* _pNext;T _val;};//List的迭代器类template<class T, class Ref, class Ptr>struct ListIterator{typedef ListNode<T>* PNode;typedef ListIterator<T, Ref, Ptr> Self;public:ListIterator(PNode pNode = nullptr):_node(pNode){}T& operator*(){return _node->_val;}T* operator->(){return &_node->_val;}Self& operator++() {_node = _node->_pNext;return *this;}Self& operator++(int){Self tmp(*this);_node = _node->_pNext;return tmp;}Self& operator--(){_node = _node->_pPre;return *this;}Self& operator--(int){Self tmp(*this);_node = _node->_pPre;return tmp;}bool operator!=(const Self& l) const{return _node != l._node;}bool operator==(const Self& l) const{return _node == l._node;}PNode _node;};//list类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;public:///// List的构造list(const T& value = T()){CreateHead();}list(int n, const T& value = T()){for (size_t i = 0; i < n; i++){push_back(value);}}template <class Iterator>list(Iterator first, Iterator last){auto it = first;while (it!=last){push_back(*it);it++;}}list(const list<T>& l){CreateHead();for (auto& e : lt){push_back(e);}}list<T>& operator=(const list<T> l){swap(lt);return *this;}~list(){clear();delete _pHead;_pHead = nullptr;}///// List Iteratoriterator begin(){return _pHead->_pNext;//这走隐式类型转化}iterator end(){return _pHead;}const_iterator begin() const{return _pHead->_pNext;}const_iterator end() const{return _pHead;}///// List Capacitysize_t size()const{return _list_size;}bool empty()const{return _list_size == 0;}// List AccessT& front(){return _pHead->_pNext->_val;}const T& front()const{return _pHead->_pNext->_val;}T& back(){return _pHead->_pPre->_val;}const T& back()const{return _pHead->_pPre->_val;}// List Modifyvoid push_back(const T& val){insert(begin(), val);}void pop_back(){erase(--end());}void push_front(const T& val){insert(end(), val);}void pop_front(){erase(begin());}// 在pos位置前插入值为val的节点iterator insert(iterator pos, const T& val){Node* node = new Node(val);Node* pre = pos._node->_pPre;pre->_pNext = node;pos._node->_pPre = node;node->_pNext = pos._node;node->_pPre = pre;++_list_size;return node;}// 删除pos位置的节点,返回该节点的下一个位置iterator erase(iterator pos){assert(pos != end());//不能释放哨兵位头节点Node* pre = pos._node->_pPre;Node* next = pos._node->_pNext;pre->_pNext = next;next->_pPre = pre;delete pos._node;--_list_size;return next;}void clear(){auto it = begin();while (it != end()){it = erase(it);}_list_size = 0;}void swap(list<T>& l){std::swap(_pHead, l._pHead);std::swap(_list_size, l._list_size);}private:void CreateHead(){_pHead = new Node;_pHead->_pNext = _pHead->_pPre = _pHead;_list_size = 0;}Node* _pHead;size_t _list_size = 0;};
}

五、list和vector的对比

在这里插入图片描述

相关文章:

初识c++——list

一、list 1、list结构 c中list为双向带头循环列表&#xff1a; 二、list接口 1、构造 using namespace std; #include<iostream> #include<list> #include<vector> int main() {list<int> lt; //构造空的listlist<int> lt1(10, 1); //构造的l…...

angular入门基础教程(八)表单之双向绑定

绑定表单数据 为了让表单使用 Angular 的特性实现数据绑定&#xff0c;需要导入 FormsModule。 这个比 vue 要繁琐点&#xff0c;不复杂&#xff0c;但是比 react 的自己手动实现要方便&#xff0c;ng 帮我们实现了双向绑定 import { Component } from "angular/core&qu…...

【C++】C++中的find方法介绍

目录 一.find方法基本用法 1.查找字符 2.查找子字符串 3.查找子字符串&#xff08;从指定位置开始&#xff09; 4.查找字符范围 5.查找不包含特定字符的范围 二.使用string::npos返回无效位置 三.总结 在C中&#xff0c; std::string 类的 find 成员函数用于查找子字…...

JVM—HotSpot虚拟机对象探秘

1、对象的创建 对象只是普通对象&#xff0c;不包括数组和Class对象 类加载检查&#xff1a;当虚拟机遇到字节码New指令时&#xff0c;先检查这个指令的参数是否可以在常量池定位到一个类的符号引用&#xff0c;并且加载这个符号引用代表的类是否被加载、解析、验证、初始化过。…...

AI测试:人工智能模型的核心测试指标,分类判别、目标检测、图像分割、定量计算分别有哪些指标?

在前面的人工智能测试技术系列文章中&#xff0c;我们详细介绍了人工智能测试的技术方法和实践流程。在了解人工智能测试方法后&#xff0c;我们需要进一步学习和研究如何衡量这些方法的有效性&#xff0c;即人工智能模型测试指标的选择。测试指标的选择主要取决于模型的类型和…...

探索LLM世界:新手小白的学习路线图

随着人工智能的发展&#xff0c;语言模型&#xff08;Language Models, LLM&#xff09;在自然语言处理&#xff08;NLP&#xff09;领域的应用越来越广泛。对于新手小白来说&#xff0c;学习LLM不仅能提升技术水平&#xff0c;还能为职业发展带来巨大的机遇。那么&#xff0c;…...

Linux基础命令大全 持续更新中......

最近重新学习了linux基础知识&#xff0c;并整理出了以下内容&#xff0c;以供参考 最近几日后续会持续更新内容哦 用户管理 加括号的代表可以不写 useradd &#xff08;参数选项&#xff09; 用户名 添加新用户 passwd &#xff08;参数选项&#xff09; 用户名 用…...

CPU的起源与发展历程

CPU的起源与发展历程 文章目录 CPU的起源与发展历程前言指令概念电子管&#xff08;真空管&#xff09;体系结构冯诺依曼架构哈佛架构 晶体管集成电路指令集与微架构微处理器x86架构CISC与RISC的提出MIPS架构ARM架构RISC-V架构FPGA 总结 前言 ​ 从古至今&#xff0c;人类为了…...

【C语言】 二叉树创建(结构体,先序遍历,中序遍历,后续遍历)

二叉树的创建&#xff1a;首先先定义一个结构体&#xff0c;里面包含数据&#xff08;data&#xff09;&#xff0c;指向左子树的指针&#xff08;L&#xff09;&#xff0c;指向右子树的指针&#xff08;R&#xff09;三个部分 在创建树的函数中&#xff0c;首先先输入…...

【和相同的二元子数组】python刷题记录

R2-前缀和专题 目录 前缀和哈希表 双指针 ps: 第一眼过去&#xff0c;这题应该能用双指针解出来&#xff0c;应该也能用前缀和解题。 前缀和哈希表 适用于 nums[i] 值不固定为 0 和 1 的其他情况 class Solution:def numSubarraysWithSum(self, nums: List[int], goal: i…...

【单片机毕业设计选题24087】-基于北斗系统的智能路灯

系统功能: 系统操作说明&#xff1a; 上电后OLED显示 “欢迎使用智能路灯系统请稍后”&#xff0c;两秒后显示Connecting...表示 正在连接阿里云&#xff0c;正常连接阿里云后显示第一页面&#xff0c;如长时间显示Connecting...请 检查WiFi网络是否正确。 系统分为四种模…...

[Docker][Docker常用命令]详细讲解

目录 1.帮助命令2.镜像命令3.容器命令4.卷命令5.常用命令 1.帮助命令 docker version # 显示docker的版本信息 docker info # 显示docker的系统信息&#xff0c;包括镜像和容器的数量 docker 命令 --help # 某条命令的帮助命令2.镜像命令 查看所有本地的主机上的镜像…...

onlyoffice用nginx反向代理

我对于onlyoffice的需求就是当个在线编辑器使用。在集成react的时候之前都是写的绝对路径的地址&#xff0c;这样在需要迁移应用的时候就造成了巨大的麻烦&#xff0c;所以我决定用nginx做反向代理&#xff0c;这样我集成的时候就不用每次都修改源码中的地址了。 一开始写的代…...

JavaScript字符串转换成base64编码方法

// base64编码表 const base64EncodeChars ref<string>("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789/" );/*** base64编码* param {Object} str*/ const base64encode (str: string) > {let result "";// 循环遍历字符串…...

25.惰性队列

介绍 消费者由于各种原因而致使长时间不能消费消息造成堆积。比如有一百万条消息发送到mq中&#xff0c;消费者这时宕机了不能消费消息&#xff0c;造成了消息堆积。惰性队列就有必要了。 正常情况下&#xff0c;消息保存在内存中。消费者从内存中读取消息消费&#xff0c;速…...

ControlNet on Stable Diffusion

ControlNet on Stable Diffusion 笔记来源&#xff1a; 1.Adding Conditional Control to Text-to-Image Diffusion Models 2.How to Use OpenPose & ControlNet in Stable Diffusion 3.ControlNet与DreamBooth&#xff1a;生成模型的精细控制与主体保持 4.Introduction t…...

源码编译安装,及nginx服务控制、监控块

1.源码编译安装&#xff1a; [root17dns ~]# wget https://nginx.org/download/nginx-1.27.0.tar.gz 2.解压&#xff1a; [root17dns ~]# tar -zxvf nginx-1.27.0.tar.gz 3.安装gcc等工具 [root17dns ~]# yum -y install gcc gcc-c [root17dns ~]# yum -y install make lrzsz …...

在react中使用wangeditor富文本

官方文档 wangeditor5在线文档 依赖安装&#xff08;react框架&#xff09; yarn add wangeditor/editor # 或者 npm install wangeditor/editor --saveyarn add wangeditor/editor-for-react # 或者 npm install wangeditor/editor-for-react --save在React 中使用wangEditor …...

拉提查合创5步玩转git工具协作代码开发

1 工具使用场景 开发团队使用git版本管理工具&#xff0c;进行协作代码开发过程中&#xff0c;最常用的场景为&#xff1a; &#xff08;1&#xff09;拉取代码 将git远端仓库最新代码拉取到本地。 &#xff08;2&#xff09;提交代码 将本地新增修改的代码提交至git远端仓库中…...

React特点

React 是一个用于构建用户界面的 JavaScript 库&#xff0c;由 Facebook 开发并维护。React 的特点主要体现在以下几个方面&#xff1a; 声明式&#xff08;Declarative&#xff09;&#xff1a;React 使你能够以一种声明的方式来描述你的 UI&#xff0c;这使得代码更加容易理解…...

超短脉冲激光自聚焦效应

前言与目录 强激光引起自聚焦效应机理 超短脉冲激光在脆性材料内部加工时引起的自聚焦效应&#xff0c;这是一种非线性光学现象&#xff0c;主要涉及光学克尔效应和材料的非线性光学特性。 自聚焦效应可以产生局部的强光场&#xff0c;对材料产生非线性响应&#xff0c;可能…...

ES6从入门到精通:前言

ES6简介 ES6&#xff08;ECMAScript 2015&#xff09;是JavaScript语言的重大更新&#xff0c;引入了许多新特性&#xff0c;包括语法糖、新数据类型、模块化支持等&#xff0c;显著提升了开发效率和代码可维护性。 核心知识点概览 变量声明 let 和 const 取代 var&#xf…...

2.Vue编写一个app

1.src中重要的组成 1.1main.ts // 引入createApp用于创建应用 import { createApp } from "vue"; // 引用App根组件 import App from ./App.vue;createApp(App).mount(#app)1.2 App.vue 其中要写三种标签 <template> <!--html--> </template>…...

学校招生小程序源码介绍

基于ThinkPHPFastAdminUniApp开发的学校招生小程序源码&#xff0c;专为学校招生场景量身打造&#xff0c;功能实用且操作便捷。 从技术架构来看&#xff0c;ThinkPHP提供稳定可靠的后台服务&#xff0c;FastAdmin加速开发流程&#xff0c;UniApp则保障小程序在多端有良好的兼…...

从零实现STL哈希容器:unordered_map/unordered_set封装详解

本篇文章是对C学习的STL哈希容器自主实现部分的学习分享 希望也能为你带来些帮助~ 那咱们废话不多说&#xff0c;直接开始吧&#xff01; 一、源码结构分析 1. SGISTL30实现剖析 // hash_set核心结构 template <class Value, class HashFcn, ...> class hash_set {ty…...

JDK 17 新特性

#JDK 17 新特性 /**************** 文本块 *****************/ python/scala中早就支持&#xff0c;不稀奇 String json “”" { “name”: “Java”, “version”: 17 } “”"; /**************** Switch 语句 -> 表达式 *****************/ 挺好的&#xff…...

人机融合智能 | “人智交互”跨学科新领域

本文系统地提出基于“以人为中心AI(HCAI)”理念的人-人工智能交互(人智交互)这一跨学科新领域及框架,定义人智交互领域的理念、基本理论和关键问题、方法、开发流程和参与团队等,阐述提出人智交互新领域的意义。然后,提出人智交互研究的三种新范式取向以及它们的意义。最后,总结…...

Netty自定义协议解析

目录 自定义协议设计 实现消息解码器 实现消息编码器 自定义消息对象 配置ChannelPipeline Netty提供了强大的编解码器抽象基类,这些基类能够帮助开发者快速实现自定义协议的解析。 自定义协议设计 在实现自定义协议解析之前,需要明确协议的具体格式。例如,一个简单的…...

基于Python的气象数据分析及可视化研究

目录 一.&#x1f981;前言二.&#x1f981;开源代码与组件使用情况说明三.&#x1f981;核心功能1. ✅算法设计2. ✅PyEcharts库3. ✅Flask框架4. ✅爬虫5. ✅部署项目 四.&#x1f981;演示效果1. 管理员模块1.1 用户管理 2. 用户模块2.1 登录系统2.2 查看实时数据2.3 查看天…...

新版NANO下载烧录过程

一、序言 搭建 Jetson 系列产品烧录系统的环境需要在电脑主机上安装 Ubuntu 系统。此处使用 18.04 LTS。 二、环境搭建 1、安装库 $ sudo apt-get install qemu-user-static$ sudo apt-get install python 搭建环境的过程需要这个应用库来将某些 NVIDIA 软件组件安装到 Je…...