C/C++ 入门(10)list类(STL)

个人主页:仍有未知等待探索-CSDN博客

专题分栏:C++

                                                        欢迎来指教!

目录

一、标准库中的list

1、了解

2、常用接口说明

a.常见的构造函数

 b.迭代器

c. Capacity​编辑

d.Element access

e.Modifiers

二、实现

1、框架 

a.节点

b.迭代器

c.链表

2、节点

3、迭代器 

 4、链表

三、反向迭代器

四、问题

1、迭代器中的箭头操作符为什么返回的是地址?


一、标准库中的list

1、了解

list:是一个双向带头循环链表,不支持随机访问(即下标访问),任意位置的插入删除效率高。

2、常用接口说明

a.常见的构造函数

list的构造函数
构造函数接口说明
list(size_t n, const T& val = t())构造n个值为val的list
list()构造空的list

list(const list& x)

拷贝构造
list(iterator first, iterator second)用[first, second)构造list

 b.迭代器

迭代器可以看作是一个指向节点的指针。

(rbegin和rend是反向迭代器,rbegin是指向了链表的尾部,rend是指向了链表的头部)

注意:

 begin,进行++操作是往后面走。

rbegin,进行++操作是往前面走。

c. Capacity

d.Element access

e.Modifiers

二、实现

 老规矩,我们还是先对结构进行分析。 

链表:除了一些对链表的基本操作之外,还需要有迭代器和节点。

1、框架 

#include <cstring>
#include <iostream>
using namespace std;// 开辟一个自己的命名空间
namespace my
{// 链表节点// 迭代器// 链表
}

a.节点

// 链表节点
template<class T>
struct ListNode
{ListNode<T>* _prev;ListNode<T>* _next;T val;// 缺省参数,如果没有传参的话,默认是T类型的无参构造// 这样做是为了防止T是一个自定义类型ListNode(const T& e = T()):_prev(nullptr),_next(nullptr),val(e){}
};

b.迭代器

其实这样的迭代器是不完整的,我们在后面会对其进行扩展。

template<class T>
struct NodeIterator
{// 对于节点和迭代器的重命名,方便书写typedef ListNode<T> Node;// 节点	typedef NodeIterator<T> Self; // 迭代器Node* _node;// 迭代器是用节点的指针来进行构造的NodeIterator(Node* node):_node(node){}
};

c.链表

// 链表
// list是一个带头双向循环链表
template<class T>
class list
{typedef ListNode<T> Node;// 节点
public:typedef NodeIterator<T, T&, T*> iterator;// 迭代器
private:Node* _head;// 链表的头部size_t _size;// 链表的长度
};

2、节点

其实节点这部分没有什么可以讲解的。唯一一个要理解的就是这个(const T& e = T())。

//const T& e = T()
// 首先T()是一个匿名对象的写法
// 为什么我们需要用到一个匿名对象,而不是一个const T& e = 值?
// 1、我们不知道T是什么类型,不知道值可以设成一个什么类型的值
// 2、如果我们设置成一个内置类型,而T是一个自定义类型的话,类型不匹配
ListNode(const T& e = T()):_prev(nullptr),_next(nullptr),val(e){}

3、迭代器 

 我之前框架里所写的就是老版本的迭代器。

新版本里面的迭代器主要添加了两个新的模板变量(Ref,Ptr),引入的这两个变量是对解引用和引用的重写。

思考题:怎么写const版本的迭代器呢?

答:新版本写法的迭代器可以直接这么写(以int为例):

NodeIterator<int, const int&, const int*>

思考题:反向迭代器怎么实现的?

标准库里面的begin()和end() 与 rbegin()和rend()采用的是对称法。

// 迭代器
// 新版本
// 链表迭代器:模仿指针的行为
// Ref:引用,Ptr指针
template<class T, class Ref, class Ptr>
struct NodeIterator
{typedef ListNode<T> Node;// 节点	typedef NodeIterator<T, Ref, Ptr> Self; // 迭代器Node* _node;NodeIterator(Node* node):_node(node){}// 前置++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(_node);_node = _node->_prev;return tmp;}// 解引用Ref operator*(){return _node->val;}// -> Ptr operator->(){return &_node->val;}// ==bool operator==(const Self& s){return _node == s._node;}// !=bool operator!=(const Self& s){return !(*this == s); }
};老版本:缺点:无法实现const的迭代器链表迭代器:模仿指针的行为
//template<class T>
//struct NodeIterator
//{
//	typedef ListNode<T> Node;// 节点
//	typedef NodeIterator<T> Self; // 迭代器
//
//	Node* _node;
//
//	NodeIterator(Node* node)
//		:_node(node)
//	{}
//	// 前置++
//	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(_node);
//		_node = _node->_prev;
//		return tmp;
//	}
//	// 解引用
//	T& operator*()
//	{
//		return _node->val;
//	}
//	// ==
//	bool operator==(const Self& s)
//	{
//		return _node == s._node;
//	}
//	// !=
//	bool operator!=(const Self& s)
//	{
//		return !(*this == s); 
//	}
//
//	// -> 
//	T* operator->()
//	{
//		return &_node->val;
//	}
//};
// 反向迭代器
template<class Iterator, class Ref, class Ptr>
struct Reverse_iterator
{typedef Reverse_iterator<Iterator, Ref, Ptr> Self;Iterator _it;Reverse_iterator(Iterator it):_it(it){}Ref operator*(){Iterator tmp(_it);return *( -- tmp);}Ptr operator->(){//return &_it.operator->();return &(_it.operator*());}Self& operator++(){_it -- ;return *this;}Self& operator--(){_it ++;return *this;}bool operator!=(const Self& s){return _it != s._it;}
};

 4、链表

// 链表
template<class T>
class list
{typedef ListNode<T> Node;
public:typedef NodeIterator<T, T&, T*> iterator;typedef NodeIterator<T, const T&, const T*> const_iterator;// 构造函数list ():_size(0){_head = new Node;_head -> _next = _head;_head -> _prev = _head;}list (size_t n, const T& val = T()):_size(0){_head = new Node;_head -> _next = _head;_head -> _prev = _head;for (size_t i = 0; i < n; i ++ ){push_back(val);}}list (list<T>& x):_size(0){_head = new Node;_head -> _next = _head;_head -> _prev = _head;iterator it = x.begin();while (it != x.end()){push_back(*it);it ++ ;}}list (iterator first, iterator last):_size(0){_head = new Node;_head -> _next = _head;_head -> _prev = _head;iterator it = first;while (it != last){insert(end(), *it);it ++ ;}}~list(){clear();delete _head;_head = nullptr;}// 访问// const版本的迭代器,迭代器的指向的内容不能被修改// 1、自己单独实现一个const版本的迭代器// 2、将const和非const合成一个,通过模板参数进行控制const_iterator begin() const{return _head->_next;}const_iterator end() const{return _head;}iterator begin(){return iterator(_head->_next);}iterator end(){return iterator(_head);}// list capacitybool empty(){return _size == 0;}size_t size(){return _size;}// list element accessT& front(){return *begin();}T& back(){return *end();}// list modifiers/*void push_back(const T& val){Node* tmp = new Node;tmp -> val = val;Node* tail = _head -> _prev;tmp->_next = tail->_next;tail->_next = tmp;tmp->_prev = tail;_head->_prev = tmp;_size ++ ;}*/void push_back(const T& val){insert(end(), val);}void push_front(const T& val){insert(begin(), val);}iterator insert (iterator position, const T& val){Node* tmp = new Node(val);tmp->_next = position._node;tmp->_prev = position._node->_prev;position._node->_prev->_next = tmp;position._node->_prev = tmp;_size ++ ;return iterator(tmp);}void pop_back(){erase( -- end());}void pop_front(){erase(begin());}iterator erase (iterator position){iterator tmp(position._node->_next);position._node->_prev->_next = position._node->_next;position._node->_next->_prev = position._node->_prev;delete position._node;_size -- ;return tmp;}void clear(){while (_size){erase(begin());}}void swap(list& l){std::swap(_head, l._head);std::swap(_size, l._size);}private:Node* _head;size_t _size;
};

三、反向迭代器

通过前面例子知道,反向迭代器的++就是正向迭代器的--,反向迭代器的--就是正向迭代器的++,因此反向迭代器的实现可以借助正向迭代器,即:反向迭代器内部可以包含一个正向迭代器,对正向迭代器的接口进行包装即可。

四、问题

1、迭代器中的箭头操作符为什么返回的是地址?

 答:其实是编译器省略了一个箭头,例如:Iterator it;

正常的调用是:it.operator->()->val; 省略了一个箭头是为了提高代码的可读性。

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

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

相关文章

简单易懂的Java Queue入门教程!

哈喽&#xff0c;各位小伙伴们&#xff0c;你们好呀&#xff0c;我是喵手。运营社区&#xff1a;C站/掘金/腾讯云&#xff1b;欢迎大家常来逛逛 今天我要给大家分享一些自己日常学习到的一些知识点&#xff0c;并以文字的形式跟大家一起交流&#xff0c;互相学习&#xff0c;一…

如何建设智慧党校

随着信息技术的飞速展开&#xff0c;特别是近年移动互联网技术&#xff0c;物联网技术&#xff0c;人工智能技术&#xff0c;大数据数据的深入展开&#xff0c;我国快速的进入信息化社会&#xff0c;信息化对各行各业的改造越来越深入&#xff0c;任何职业&#xff0c;任何安排…

SSM【Spring SpringMVC Mybatis】—— Spring(一)

目录 1、初识Spring 1.1 Spring简介 1.2 搭建Spring框架步骤 1.3 Spring特性 1.5 bean标签详解 2、SpringIOC底层实现 2.1 BeanFactory与ApplicationContexet 2.2 图解IOC类的结构 3、Spring依赖注入数值问题【重点】 3.1 字面量数值 3.2 CDATA区 3.3 外部已声明be…

浅谈ArrayList和LinkedList的区别

ArrayList和LinkedList在Java中都是常用的List接口的实现类&#xff0c;但它们之间存在一些显著的区别。 实现方式&#xff1a; ArrayList&#xff1a;基于数组实现。内部使用一个动态数组来存储元素&#xff0c;这意味着可以通过索引快速访问元素&#xff0c;时间复杂度为O(1)…

算法学习笔记(Nim游戏)

N i m Nim Nim游戏 n n n堆物品&#xff0c;每堆有 a i a_i ai​个&#xff0c;每个玩家轮流取走任意一堆的任意个物品&#xff0c;但不能不取&#xff0c;取走最后一个物品的人获胜。 N i m Nim Nim游戏是一种经典的公平组合游戏。现在对它进行分析。 首先定义两个博弈中的状…

【Chisel】chisel中怎么处理类似verilog的可变位宽和parameter

在 Chisel 中处理可变位宽和参数的方式与 Verilog 有一些不同&#xff0c;因为 Chisel 是建立在 Scala 语言之上的。以下是如何在 Chisel 中处理这些概念的方法&#xff1a; 参数化&#xff08;Parameters&#xff09; 在 Chisel 中&#xff0c;参数化是通过在模块构造函数中定…

VUE使用饿了么的上传组件时实现图片预览

创作灵感 最近在写项目时&#xff0c;遇到了上传头像的需求&#xff0c;我使用的是element组件中的upload组件。但是在使用时&#xff0c;我需要实现预览、手动上传头像等功能。然而在使用饿了么组件时&#xff0c;这些功能还是需要我们自己去手动实现的&#xff0c;在手动实现…

Linux makefile进度条

语法 在依赖方法前面加上就不会显示这一行的命令 注意 1.make 会在当前目录下找名为“makefile” 或者 “Makefile” 的文件 2.为了生成第一依赖文件&#xff0c;如果依赖文件列表有文件不存在&#xff0c;则会到下面的依赖关系中查找 3..PHONY修饰的依赖文件总是被执行的 …

Redis——RDB、AOF和混合持久化机制

Redis提供了三种持久化机制来确保数据的持久保存&#xff0c;分别是RDB&#xff08;Redis DataBase&#xff09;、AOF&#xff08;Append Only File&#xff09;和混合持久化。 RDB&#xff08;Redis DataBase&#xff09; RDB持久化机制是将Redis在内存中的数据保存到磁盘上的…

xss-lab 1-18关payload

Less-1 ?name<script>alert()</script> Less-2 "><script>alert()</script> "οnclick"alert() " οnfοcus"alert() " οnblur"alert() Less-3 οnfοcusalert() οnbluralert() οnfοcusjavascript:aler…

Spring AopUtils深度解析:从入门到精通的全方位指南

1. 概述 AopUtils是Spring框架中的一个工具类&#xff0c;主要用于处理AOP&#xff08;面向切面编程&#xff09;相关的操作。它提供了一系列静态方法&#xff0c;帮助开发者更方便地处理AOP中的对象、代理以及通知&#xff08;Advice&#xff09;等。 2. 用途 AopUtils的主要…

操作系统原理与系统——实验十三多道批处理作业调度(作业可移动)

关键代码 #include<stdio.h> #include<stdlib.h> #include<string.h> typedef struct data{int hour;//当前小时int min;//当前分钟 }time; struct node{char name[20];//进程名time arrive;//到达就绪队列时间int zx;//执行时间(预期时间)int size;int ta…

Polygon市值机器人

随着区块链技术的蓬勃发展和数字货币市场的日益繁荣&#xff0c;投资者们对于如何精准把握市场动态、实现资产稳健增长的需求愈发迫切。在这个背景下&#xff08;市值管理飞//机//aishutuyu&#xff09;&#xff0c;Polygon市值机器人应运而生&#xff0c;作为一款基于Polygon公…

LeetCode 第397场周赛个人题解

目录 100296. 两个字符串的排列差 原题链接 思路分析 AC代码 100274. 从魔法师身上吸取的最大能量 原题链接 思路分析 AC代码 100281. 矩阵中的最大得分 原题链接 思路分析 AC代码 100312. 找出分数最低的排列 原题链接 思路分析 AC代码 100296. 两个字符串的排…

timerfd加epoll封装定时器

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 1、用timerfd加epoll封装定时器的优点2、代码实现 1、用timerfd加epoll封装定时器的优点 定时器为什么需要timerfd 在设计定时器时&#xff0c;我们首先想到的就是…

【SpringBoot】Redis Lua脚本实战指南:简单高效的构建分布式多命令原子操作、分布式锁

文章目录 一.Lua脚本1.Lua特性2.Lua优势 二.Lua语法1.注释2.变量3.数据类型&#xff1a;3.1.基本类型3.2.对象类型&#xff1a;表&#xff08;table&#xff09; 4.控制结构&#xff1a;4.1.条件语句: 使用if、else和elseif来实现条件分支。4.2.循环结构&#xff1a;Lua支持for…

Shell参数扩展形式学习笔记

Shell参数扩展形式学习笔记 文章目录 Shell参数扩展形式学习笔记空值判断处理 ${parameter:-word} ${parameter:word} ${parameter:?word} ${parameter:word}变量位置截取 ${parameter:offset} ${parameter:offset:length}变量匹配组合 ${!prefix*} ${!prefix} ${!name[]} ${!…

感知机和神经网络

引入 什么是神经网络&#xff1f; 我们今天学习的神经网络&#xff0c;不是人或动物的神经网络&#xff0c;但是又是模仿人和动物的神经网络而定制的神经系统&#xff0c;特别是大脑和神经中枢&#xff0c;定制的系统是一种数学模型或计算机模型&#xff0c;神经网络由大量的人…

图像处理:图像噪声添加

文章目录 前言一、高斯噪声二、椒盐噪声三、泊松噪声四、斑点噪声五、指数噪声六、均匀噪声总结 前言 本文主要介绍几种添加图像噪声的方法&#xff0c;用于数据增强等操作。 以下图为例。 一、高斯噪声 高斯噪声就是给图片添加一个服从高斯分布的噪声&#xff0c;可以通过调…

vLLM初探

vLLM是伯克利大学LMSYS组织开源的大语言模型高速推理框架&#xff0c;旨在极大地提升实时场景下的语言模型服务的吞吐与内存使用效率。vLLM是一个快速且易于使用的库&#xff0c;用于 LLM 推理和服务&#xff0c;可以和HuggingFace 无缝集成。vLLM利用了全新的注意力算法「Page…