c++:list

1.list的使用

1.1构造

1.2迭代器遍历

(1)迭代器是算法和容器链接起来的桥梁

容器就是链表,顺序表等数据结构,他们有各自的特点,所以底层结构是不同的。在不用迭代器的前提下,如果我们的算法要作用在容器上面,不可避免的需要获取底层结构,这不仅会增加耦合度,而且也不利于算法库的实现。所以我们创建一个迭代器,将底层结构的访问方式封装成迭代器,直接利用迭代器去访问容器。

有两个好处,

其一,我们不用根据各种各样的容器去一直创造新的算法兼容,保证了算法库的可维护性

其二,我们的访问更加简单了,都用迭代器访问,不需要对各种容器的底层有很多了解

1.3首尾元素访问

1.4插入数据

第一行表示在it迭代器的位置插入一个2

第二行表示在it位置插入三个1

第三行创建了有两个元素值为10的链表,然后第四行把test从头到尾的节点值都插入到了it位置

1.5删除数据

还有一个删除函数:remove

他会删除所有指定值的元素

这里我们删除10这个值之前second里面有两个10

我们进行remove(10)后,list里面的10都被删除了。

1.6交换链表

1.7清除所有有效数据

1.8排序

list自带的排序效率很低

甚至我们先把数据拷贝给vector,用vector排完序之后再给回list,此时我们list自己排序花的时间比拷贝到vector排完序再拷贝回来还要慢。

1.9splice(剪贴)

splice的作用是把list中某一段迭代器区间的内容移动到pos迭代器的位置的前面,就像剪切一样

一共有三种用法

第一种:把整个list剪切到pos迭代器位置

这里我们看到一开始second是有四个节点,经过整个second的剪切, second变成空链表,而first则具有了second的四个节点

第二种:把list的it位置节点剪切到pos迭代器位置

这里我们看到,成功的把second的第一个节点剪切到了first上

第三种:把list中一段迭代器区间的内容剪切到pos迭代器位置

这里我们把second的后面三个节点都剪切到了first中

2.list的模拟实现

2.1节点

2.1.1结构

由于我们实现的是双向带头循环链表,所以我们节点中需要存有前一个和下一个节点的地址,以及最基本的节点的值。

注意:因为我们实现的是模板的链表节点,所以才要写成list_node<T>.

疑问:我们不是不希望暴露底层结构吗?为什么这里用struct?

首先,我们后面的list需要频繁使用到节点内的指针等

其次,因为每个编译器内部实现的时候命名没有统一,所以我们就算想访问也是很难的

2.1.2构造函数

这里我们使用匿名对象来给到缺省值,对于自定义类型和内置类型都可以有效

内置类型:

自定义类型:

自定义类型会调用对应的构造函数

2.2迭代器

2.2.1结构

这里的迭代器底层是指向链表节点的指针,但是迭代器的类型实际上是一个自定义类型

让自定义类型充当迭代器的原因:对于链式结构,内置类型指针无法实现++移动到下一个元素的迭代器位置,所以我们需要把它封装成自定义类型,通过运算符重载实现++移动到下一个元素迭代器位置。

简单来说,原生指针指向地址的功能没问题,但是移动到下一个元素的内置元素运算符逻辑无法满足链式结构的遍历,所以需要我们把迭代器类型设置为自定义类型,通过自定义类型的运算符重载实现链式遍历。

2.2.2构造函数

因为结构中只有一个指向链表节点的指针,所以这里我们只要用node初始化即可

2.2.3运算符重载

(1)解引用

1.非const迭代器版本

解引用就是为了访问节点的值,所以我们直接返回m_date

2.const迭代器版本

const T& operator*()
{return node->m_date;
}

这里返回的是const就保证了指向的内容不可改变,注意我们不可以在函数后面加const,如果那样加就表示迭代器本身不可改变了

(2)++与--

++是为了我们可以访问到下一个节点的位置,而下一个节点的位置我们可以通过

node->next访问,把node更新一下就行

(3)!=

判断迭代器指向的位置是否相等只要判断他们的node就行

(4)==

(5)->

当我们的数据类型是自定义类型的时候,我们有两种方法访问该自定义类型内的值

第一种:解引用然后用.访问

第二种:->再用->访问(场景比较固定)

比如说我们的list中存的是A类型对象,那么我们要访问到a1就需要先访问节点中的m_date(A类型数据),然后再访问a1或a2.

(1)非const版本

我们返回的是A类型的指针,然后再->访问a1或者a2。

为了保证可读性,我们不会用两个->去表示,而是直接缩略成一个->

(2)const版本

2.2.4const与非const迭代器合并

我们首先要添加两个模板参数,Ref和Ptr。

Ref表示引用(&),Ptr表示指针(*)

因为const和非const只有两个方法存在区别,所以我们把这两个方法的返回值设置为模板参数

然后我们在list中typedef即可

2.3链表

2.3.1结构

因为我们是双向链表,所以只需要知道头结点地址即可

2.3.2构造函数与析构函数

构造函数

我们的目标是构建一个节点,且该节点自成循环

拷贝构造

为了方便调用构造函数空初始化的功能,我们单独写一个empty_init方法,并调用他来为l2初始化

我们先给l2创建一个头结点初始化,然后复用push_back插入数据即可

析构函数

我们首先要写一个方法用来删除链表的所有有效节点,然后再释放list的哨兵节点

2.3.3尾插

第一步:根据传的值创建节点

第二步:调整节点指向

2.3.4 begin与end

因为头结点是不存储有效数据的,所以begin是head的下一个节点

而end是最后一个有效节点的下一个节点,所以是m_head

这个就是const版本的begin和end

2.3.5insert

第一步:记录前一个节点和下一个节点,并创建出cur节点

第二步:修改指向关系

注意:这里不存在扩容,所以也就没有迭代器失效的问题,我们的it仍然是有效的

2.3.6erase 

注意:

(1)it迭代器会失效,因为这个位置节点被删除了,空间也释放了

(2)为了方便后续的使用,我们需要返回删除后顶替上原本节点的迭代器

2.3.7赋值重载

因为传参的时候就调用了一次拷贝构造,所以l1就是被拷贝链表的深拷贝,把l1和*this交换后,调用赋值符号的对象就相当于完成了深拷贝。且由于l1是临时变量,所以他会调用析构函数释放掉,而调用赋值的对象则不会。

2.3.8改进结构

因为我们对容器的操作经常涉及size的获取,所以我们要写一个size方法。

但是对于链表这个结构,要获取size还要我们遍历一次链表,效率太低下了。于是我们可以在list的结构中加上m_size,并在构造函数和insert,erase这种设计节点数变化的方法中更新size的值。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/14709.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

《Wiki.js知识库部署实践 + CNB Git数据同步方案解析》

一、wiki.js 知识库简介 基本概述 定义 &#xff1a;Wiki.js 是一个开源、现代、轻量且功能强大的 Wiki 应用程序&#xff0c;基于 Node.js 构建&#xff0c;旨在帮助个人和团队轻松创建、管理和共享知识。开源性质 &#xff1a;它遵循 AGPLv3 许可证&#xff0c;任何人都可以…

ip地址是手机号地址还是手机地址

在数字化生活的浪潮中&#xff0c;IP地址、手机号和手机地址这三个概念如影随形&#xff0c;它们各自承载着网络世界的独特功能&#xff0c;却又因名称和功能的相似性而时常被混淆。尤其是“IP地址”这一术语&#xff0c;经常被错误地与手机号地址或手机地址划上等号。本文旨在…

微服务 day01 注册与发现 Nacos OpenFeign

目录 1.认识微服务&#xff1a; 单体架构&#xff1a; 微服务架构&#xff1a; 2.服务注册和发现 1.注册中心&#xff1a; 2.服务注册&#xff1a; 3.服务发现&#xff1a; 发现并调用服务&#xff1a; 方法1&#xff1a; 方法2&#xff1a; 方法3:OpenFeign OpenFeig…

网络安全:挑战、技术与未来发展

&#x1f4dd;个人主页&#x1f339;&#xff1a;一ge科研小菜鸡-CSDN博客 &#x1f339;&#x1f339;期待您的关注 &#x1f339;&#x1f339; 1. 引言 在数字化时代&#xff0c;网络安全已成为全球关注的焦点。随着互联网的普及和信息技术的高速发展&#xff0c;网络攻击的…

PostgreSql-COALESCE函数、NULLIF函数、NVL函数使用

COALESCE函数 COALESCE函数是返回参数中的第一个非null的值&#xff0c;它要求参数中至少有一个是非null的; select coalesce(1,null,2),coalesce(null,2,1),coalesce(null,null,null); NULLIF(ex1,ex2)函数 如果ex1与ex2相等则返回Null&#xff0c;不相等返回第一个表达式的值…

neo4j-解决导入数据后出现:Database ‘xxxx‘ is unavailable. Run :sysinfo for more info.

目录 问题描述 解决方法 重新导入 问题描述 最近在linux上部署了neo4j&#xff0c;参照之前写的博客:neo4j-数据的导出和导入_neo4j数据导入导出-CSDN博客 进行了数据导出、导入操作。但是在进行导入后&#xff0c;重新登录网页版neo4j&#xff0c;发现对应的数据库状态变…

C语言【基础篇】之数组——解锁多维与动态数组的编程奥秘

数组 &#x1f680;前言&#x1f99c;数组的由来与用途&#x1f31f;一维数组详解&#x1f58a;️二维数组进阶&#x1f4af;动态数组原理&#x1f914;常见误区扫盲&#x1f4bb;学习路径建议✍️总结 &#x1f680;前言 大家好&#xff01;我是 EnigmaCoder。本文收录于我的专…

TaskBuilder项目实战:创建项目

用TaskBuilder开发应用系统的第一步就是创建项目&#xff0c;项目可以是一个简单的功能模块&#xff0c;也可以是很多功能模块的集合&#xff0c;具体怎么划分看各位的实际需要&#xff0c;我们一般会将相互关联比较紧密的一组功能模块放到一个独立的项目内&#xff0c;以便打包…

基于DeepSeek API和VSCode的自动化网页生成流程

1.创建API key 访问官网DeepSeek &#xff0c;点击API开放平台。 在开放平台界面左侧点击API keys&#xff0c;进入API keys管理界面&#xff0c;点击创建API key按钮创建API key&#xff0c;名称自定义。 2.下载并安装配置编辑器VSCode 官网Visual Studio Code - Code Editing…

Redis深入学习

目录 Redis是什么&#xff1f; Redis使用场景 Redis线程模型 Redis执行命令是单线程的为什么还这么快&#xff1f; Redis持久化 Redis 事务 Key 过期策略 Redis 和 mysql 如何保证数据一致&#xff1f; 缓存穿透 缓存击穿 缓存雪崩 Redis是什么&#xff1f; redis是一…

Dockerfile 文件详解

在平常的开发工作中&#xff0c;我们经常需要部署项目&#xff0c;一个项目开发完成后&#xff0c;使用 Docker 方式部署&#xff0c;那么首先得构造镜像&#xff0c;构造镜像最主要的就是 Dockerfile 文件的编写&#xff0c;今天简单来总结下 Dockerfile 文件的编写以及有哪些…

开源模型应用落地-CodeQwen模型小试-SQL专家测试(二)

一、前言 代码专家模型是基于人工智能的先进技术&#xff0c;它能够自动分析和理解大量的代码库&#xff0c;并从中学习常见的编码模式和最佳实践。这种模型可以提供准确而高效的代码建议&#xff0c;帮助开发人员在编写代码时避免常见的错误和陷阱。 通过学习代码专家模型&a…

kubeadm构建k8s源码阅读环境

目标 前面看了minikube的源码了解到其本质是调用了kubeadm来启动k8s集群&#xff0c;并没有达到最初看代码的目的。 所以继续看看kubeadm的代码&#xff0c;看看能否用来方便地构建源码调试环境。 k8s源码编译 kubeadm源码在k8s源码库中&#xff0c;所以要先克隆k8s源码。之…

LLM学习笔记1——本地部署Meta-Llama-3.2-1B大模型

系列文章目录 参考博客 参考博客 文章目录 系列文章目录前言与调用一、部署要求二、实现步骤0.深度学习环境错误1&#xff0c;验证pytorch版本时提示以下问题&#xff1a;错误2&#xff0c;验证pytorch版本时提示以下问题&#xff1a;错误3&#xff0c;有时候还会提示你有一些…

搜维尔科技:提供人形机器人传感器的应用案例分析

视觉传感器 • 家庭服务场景&#xff1a;在家庭清洁机器人中&#xff0c;视觉传感器可以识别家具、障碍物的位置和形状&#xff0c;规划清洁路径&#xff0c;避开桌椅、宠物玩具等。如小米扫地机器人&#xff0c;通过视觉传感器与算法结合&#xff0c;能构建房间地图&#xff…

windows蓝牙驱动开发-蓝牙 LE 邻近感应配置文件

邻近感应检测是蓝牙低功耗 (LE) 的常见用途。 本部分提供了创建可用于开发 UWP 设备应用的邻近感应配置文件的设备实现的指南。 在开发此应用之前&#xff0c;应熟悉蓝牙 LE 函数和蓝牙 LE 邻近感应配置文件规范。 示例服务声明 蓝牙低功耗引入了一个新的物理层&#xff0c;…

逻辑回归:Sigmoid函数在分类问题中的应用

欢迎来到我的主页&#xff1a;【Echo-Nie】 本篇文章收录于专栏【机器学习】 1 什么是Sigmoid函数&#xff1f; Sigmoid函数&#xff08;Logistic函数&#xff09;是机器学习中最经典的激活函数之一&#xff0c;是一个在生物学中常见的S型函数&#xff0c;也称为S型生长曲线。…

如何在Windows中配置MySQL?

MySQL是一个广泛使用的开源关系型数据库管理系统&#xff0c;它支持多种操作系统平台&#xff0c;其中包括Windows。无论是开发者进行本地开发&#xff0c;还是管理员为应用程序配置数据库&#xff0c;MySQL都是一个非常流行的选择。本篇文章将详细介绍如何在Windows操作系统中…

MySQL的操作

一.数据库的操作 1.创建数据库 create database (if not exists) 数据库名称 (character set/charset 字符集名称); SQL中有特定含义的单词&#xff08;create database&#xff09;也就是关键字 在创建数据库名 表名 列名的时候都可以和关键字重复 。 if not exists&#xff1…

MariaDB *MaxScale*实现mysql8读写分离

1.MaxScale 是干什么的&#xff1f; MaxScale是maridb开发的一个mysql数据中间件&#xff0c;其配置简单&#xff0c;能够实现读写分离&#xff0c;并且可以根据主从状态实现写库的自动切换&#xff0c;对多个从服务器能实现负载均衡。 2.MaxScale 实验环境 中间件192.168.12…