从零开始的C++(十二)

长风破浪会有时,直挂云帆济沧海。

List:

链式结构,类似带头双向循环链表。

常见成员函数:

push_back():尾插      pop_back():尾删    push_front():头插     pop_front():头删

特征:开辟的空间不连续,因此插入、删除结点效率高。但不支持随机访问,无法指定下标来快速访问。

list模拟实现:

list模拟实现包含三个类,一部分是表示链表的每个结点的类、一部分是迭代器、一部分是链表的头结点(也是哨兵结点,特征是指向第一个有效结点)。

链表结点:

    template<class T>struct ListNode{ListNode(const T& val = T()) : _pPre(nullptr), _pNext(nullptr), _val(val){}ListNode<T>* _pPre;ListNode<T>* _pNext;T _val;};

由于是双向循环链表,所以必须有前后两个指针同时_val用于保存值。

迭代器:

    template<class T, class Ref, class Ptr>class ListIterator{typedef ListNode<T>* PNode;typedef ListIterator<T, Ref, Ptr> Self;public:ListIterator(PNode pNode = nullptr) :_pNode(pNode){}ListIterator(const Self& l) : _pNode(l._pNode){}Ref operator*(){return _pNode->_val;}Ptr operator->(){return &*this;}Self& operator++(){_pNode = _pNode->_pNext;return *this;}Self operator++(int){Self temp(*this);_pNode = _pNode->_pNext;return temp;}Self& operator--(){_pNode = _pNode->_pPre;return *this;}Self& operator--(int){Self temp(*this);_pNode = _pNode->_pPre;return temp;}bool operator!=(const Self& l){return _pNode != l._pNode;}bool operator==(const Self& l){return !(*this != l);}public:PNode _pNode;};

首先,迭代器的功能类似与指针,因此唯一的元素是结点指针类型。

迭代器需要实现遍历,因此需要有++、--来进行迭代器的移动,有!=、==来判断是否到达终止条件,有*、->来实现解引用。此处迭代器适配const类型和非const类型,而const与非const的区别在于解引用的返回类型是否有const修饰,此处返回类型用Ref和Ptr代替,Ref会根据数据判断是T&还是const T&,Ptr同理。

表头节点:

 template<class T>class list{typedef ListNode<T> Node;typedef Node* PNode;public:typedef ListIterator<T, T&, T*> iterator;typedef ListIterator<T, const T&, const T&> const_iterator;public:///// List的构造list(){CreateHead();}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();// 用l中的元素构造临时的temp,然后与当前对象交换list<T> temp(l.cbegin(), l.cend());this->swap(temp);}list<T>& operator=(const list<T> l){this->swap(l);return *this;}~list(){clear();delete _pHead;_pHead = nullptr;}///// List Iteratoriterator begin(){return iterator(_pHead->_pNext);}iterator end(){return iterator(_pHead);}const_iterator begin()const{return const_iterator(_pHead->_pNext);}const_iterator end()const{return const_iterator(_pHead);}///// List Capacitysize_t size()const{size_t size = 0;ListNode* p = _pHead->_pNext;while (p != _pHead){size++;p = p->_pNext;}return size;}bool empty()const{return size() == 0;}// List AccessT& front(){assert(!empty());return _pHead->_pNext->_val;}const T& front()const{assert(!empty());return _pHead->_pNext->_val;}T& back(){assert(!empty());return _pHead->_pPre->_val;}const T& back()const{assert(!empty());return _pHead->_pPre->_val;}// List Modifyvoid push_back(const T& val){insert(end(), val);}void pop_back(){erase(--end());}void push_front(const T& val){insert(begin(), val);}void pop_front(){erase(begin());}// 在pos位置前插入值为val的节点iterator insert(iterator pos, const T& val){PNode pNewNode = new Node(val);PNode pCur = pos._pNode;// 先将新节点插入pNewNode->_pPre = pCur->_pPre;pNewNode->_pNext = pCur;pNewNode->_pPre->_pNext = pNewNode;pCur->_pPre = pNewNode;return iterator(pNewNode);}// 删除pos位置的节点,返回该节点的下一个位置iterator erase(iterator pos){// 找到待删除的节点PNode pDel = pos._pNode;PNode pRet = pDel->_pNext;// 将该节点从链表中拆下来并删除pDel->_pPre->_pNext = pDel->_pNext;pDel->_pNext->_pPre = pDel->_pPre;delete pDel;return iterator(pRet);}void clear(){iterator p = begin();while (p != end()){p = erase(p);}_pHead->_pPre = _pHead;_pHead->_pNext = _pHead;}void swap(list<T>& l){PNode tmp = _pHead;_pHead = l._pHead;l._pHead = tmp;}private:void CreateHead(){_pHead = new Node;_pHead->_pPre = _pHead;_pHead->_pNext = _pHead;}PNode _pHead;};
}

对于默认构造函数,此处调用CreateHead函数,实现了创建一个Node类型的结点,同时结点的两个指针都指向自己。

对于传值构造函数,首先调用CreateHead函数,实现了创建一个Node类型的结点,然后复用了push_back函数,实现结点的插入。

对于传迭代器的构造,先创建头结点,然后利用迭代器遍历,实现数字插入。

对于拷贝构造,先创建一个头结点,然后复用了迭代器的构造方式产生一个临时对象,然后交换临时对象和当前要创建的对象的成员变量,实现拷贝,同时利用临时对象销毁创建的头结点。此处如果不想开头创建一个头结点,则析构函数必须更改一下,只有头结点不为空的时候才调用clear函数,否则clear函数中调用的begin函数会出现非法访问的情况。

对于赋值函数,原理和拷贝构造一致,都是利用临时对象来替换,实现赋值操作。

对于头插、头删、尾插、尾删,复用insert和erase函数,但需要注意传入的迭代器是谁。

insert:在迭代器所指位置之前插入一个结点,同时返回插入结点的迭代器。

erase:删除迭代器所指位置的结点,返回下一个结点的迭代器。

clear:利用迭代器遍历链表,利用erase删除链表结点,实现删除链表除了表头节点之外的所有结点。

析构函数:在clear函数删除除表头节点外的所有结点后,销毁表头节点。

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

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

相关文章

【Java技术专题】「入门到精通系列教程」深入探索Java特性中并发编程体系的原理和实战开发指南( 实现可伸缩IO专题)— 上

深入探索Java特性中并发编程体系的原理和实战开发指南&#xff08; 实现可伸缩IO专题&#xff09; 总体内容概览可扩展的网络服务分布式对象传统的阻塞式网络服务每个请求或连接可以在独立的线程中进行处理Server服务处理请求类Handler处理逻辑类优点缺点 可扩展性目标平稳降级…

MySQL Join 类型

文章目录 1 Join 类型有哪些2 Inner Join3 Left Join4 Right Join5 Full Join 1 Join 类型有哪些 SQL Join 类型的区别 Inner Join: 左,右表都有的数据Left Join: 左表返回所有的行, 右表没有的补充为 NULLRight Loin: 右表返回所有的行, 左表没有的补充为 NULLFull Outer J…

Excel多线程导入数据库

文章目录 Excel多线程导入数据库1. CountDownLatch2.多线程导入数据库 Excel多线程导入数据库 书接上文 Excel20w数据5s导入 1. CountDownLatch CountDownLatch 维护了一个计数器&#xff0c;初始值为指定的数量。当一个或多个线程调用 await() 方法时&#xff0c;它们会被阻…

【flink sql table api】时间属性的指定与使用注意事项

文章目录 一. 时间属性介绍二. Table api指定时间属性三. 处理时间的指定1. 在创建表的 DDL 中定义2. 在 DataStream 到 Table 转换时定义3. 使用 TableSource 定义 四. 事件时间的指定1. 在 DDL 中定义2. 在 DataStream 到 Table 转换时定义3. 使用 TableSource 定义 五. 小结…

力扣每日一题70:爬楼梯

题目描述&#xff1a; 假设你正在爬楼梯。需要 n 阶你才能到达楼顶。 每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢&#xff1f; 示例 1&#xff1a; 输入&#xff1a;n 2 输出&#xff1a;2 解释&#xff1a;有两种方法可以爬到楼顶。 1. 1 阶 1 阶 …

redis 配置主从复制,哨兵模式案例

哨兵(Sentinel)模式 1 . 什么是哨兵模式&#xff1f; 反客为主的自动版&#xff0c;能够自动监控master是否发生故障&#xff0c;如果故障了会根据投票数从slave中挑选一个 作为master&#xff0c;其他的slave会自动转向同步新的master&#xff0c;实现故障自动转义 2 . 原理…

简析新能源汽车充电桩设计与应用

叶根胜 安科瑞电气股份有限公司 上海嘉定 201801 摘要&#xff1a;本文针对新能源汽车充电桩建设工作进行探究&#xff0c;采用案例分析法、文献查阅法&#xff0c;指出了新能源汽车充电桩建设存在的问题&#xff0c;阐述了充电桩建设与优化的对策。研究表明&#xff1a;目前…

php实现防止Struts2框架漏洞中的远程命令执行攻击的代码

使用PHP过滤器 PHP提供了一些内置的过滤器&#xff0c;可以过滤掉一些恶意代码。可以使用以下代码将输入数据进行过滤&#xff1a; ​$input $_POST[input]; $safe_input filter_var($input, FILTER_SANITIZE_STRING); 使用escapeshellcmd()和escapeshellarg() 可以使用PHP…

189. 轮转数组 --力扣 --JAVA

题目 给定一个整数数组 nums&#xff0c;将数组中的元素向右轮转 k 个位置&#xff0c;其中 k 是非负数。 解题思路 通过位移后位置对数组长度的取余来判断元素变换后的位置 代码展示 class Solution {public void rotate(int[] nums, int k) {int size nums.length;int[]…

python 使用json包在json格式字符串和python对象之间的变化

起因&#xff1a;使用python json包时&#xff0c;将键值对均为数字的字典存入txt文件后重新加载进字典后出现“字典key值不唯一”的神奇现象。 相关代码&#xff1a; 字典添加数据部分 def xuhao_chuti(self):rand random.randint(1, 908)if rand in self.memery.keys() an…

element-ui的日历组件el-calendar高度咋调小

最近项目首页有个空余 不知道放啥 打算放个日历card 充充位置&#xff0c; el-calendar日历组件的整体宽度可以用el-row el-col :gutter :span来控制自适应 但是官网文档没说高度咋缩小 细长一条好难看 自己尝试改了改element的样式没整出来 最后照着这位博主的方法改是好使滴…

软考系列(系统架构师)- 2014年系统架构师软考案例分析考点

试题一 软件架构&#xff08;MYC 架构、扩展接口模式&#xff09; MVC架构风格最初是Smalltalk-80中用来构建用户界面时采用的架构设计风格。其中M代表模型&#xff08;Model)&#xff0c;V代表视图&#xff08;View)&#xff0c;C代表控制器&#xff08;Controller)。在该风格…

windows/mac/linux 用C++搭建一个刷题模拟器

一个刷题模拟器&#xff0c;一定要有题&#xff0c;题目从这里下载 欢迎大家提供新题目&#xff08;请把题目文件夹压缩成zip后发给我chengyixuan130812163.com&#xff09;&#xff0c;我会定期更新的。 题目格式&#xff1a; 题目编号 nums.txt&#xff08;评测点个数&#x…

动态规划(记忆化搜索)

AcWing 901. 滑雪 给定一个 R行 C 列的矩阵&#xff0c;表示一个矩形网格滑雪场。 矩阵中第 i 行第 j 列的点表示滑雪场的第 i 行第 j 列区域的高度。 一个人从滑雪场中的某个区域内出发&#xff0c;每次可以向上下左右任意一个方向滑动一个单位距离。 当然&#xff0c;一个人能…

【前端设计模式】之桥接模式

桥接模式是一种常用的设计模式&#xff0c;它可以将抽象部分与实现部分分离&#xff0c;使它们可以独立地变化。在前端开发中&#xff0c;桥接模式可以帮助我们更好地组织和管理代码&#xff0c;提高代码的可维护性和可扩展性。 桥接模式特性 分离抽象和实现&#xff1a;桥接…

liunx Centos-7.5上 rabbitmq安装

在安装rabbitmq中需要注意&#xff1a; 1、rabbitmq依赖于erlang&#xff0c;需要先安装erlang 2、erlang和rabbitmq版本有对应关系 可参考网页&#xff1a;https://www.rabbitmq.com/which-erlang.html 第一步&#xff0c;安装编译工具及库文件,如果服务器上已经有了&…

长连接的原理

Apollo的长连接实现是 Spring的DeferredResult来实现的,先看怎么用 import ...RestController RequestMapping("deferredResult") public class DeferredResultController {private Map<String, Consumer<DeferredResultResponse>> taskMap new HashMa…

SpringBoot_minio sdk使用自签名https证书错误处理

minio sdk使用自签名https证书错误处理 1.问题描述1.1 报错日志1.2 maven 依赖配置1.3 当前spring MinioClient配置 2.问题分析3.问题解决3.1 使用受信任的证书3.2 忽略证书验证3.2.1 minio客户端3.2.2 minio sdk 忽略证书验证3.2.2.1 拓展: 补充minioclient请求日志 4. 问题总…

树形数据增删改查

功能描述&#xff1a; 默认展示所有项目点击项目展示当前项目下的所有区域点击区域展示当前区域下的所有工位以上以树形图格式展示项目&#xff0c;区域&#xff0c;和工位都可进行增加 修改 和删除&#xff0c;每个图标hover时显示对应提示信息项目&#xff0c;区域&#xff…

illuminate/database 使用 二

上一篇文章写怎么单独使用illuminate/database&#xff0c;这回讲下怎么整合到项目里使用。为此特意看了下laravel对其使用。本篇文章&#xff0c;参照laravel的使用&#xff0c;简单实现。 一 原理 laravel 里使用illuminate/config。 illuminate/config composer 地址&…