植物大战 List——C++
这里写目录标题
- vector和stirng的细节
- 对于string
- list的使用
- list的迭代器
- 反向迭代器
- 构造函数
- 关于list::sort的排序
- unique
- list的底层模拟实现
- 结点类的实现
- 迭代器模拟实现
- list实现
- 插入的实现
- 迭代器失效
- insert
- erase
- 析构函数
- 拷贝构造
- 赋值构造函数
vector和stirng的细节
复习vector的深浅拷贝。
下图是vector<vector< int>> 的底层模型
实际和动态二维数组的图一样。
vv[i][j] 表示什么意思?
vv[ i]表示访问第几个vector,
vv[i][ j]表示访问第i个vector的第j个下表的元素。
对于string
class string
{
private:char _buf[16];char* _ptr;size_t _size;size_t _capacity;
}
string设计如下,string在设计时用了一个buf的数组,buf大小是16,最后一个空间是给\0的。
这样设计的目的是小于16byte的字符串,存在buf数组中。大于等于16的字符串存在_ptr指向的空间。
list的使用
概念:list是一个容器,允许在常数O(1)时间,在任意位置进行insert和erase。他的迭代器是双向的。
链表在使用上和vector和string差不多。
因为支持O(1)的时间,所以它是双向循环链表的数据结构。
如图
对于迭代器的位置,begin()是第一个元素的位置,end()是最后一个元素的下一个位置,也就是哨兵位头结点。
list的迭代器
对于list为什么要学迭代器?
对于string和vector来说,使用的是原生指针,所以迭代器是原生的,对于list,我们也要封装迭代器,因为list底层是地址,不是连续的地址。为了方便用户操作,比如for循环遍历,范围for等。
小细节:因为list的结构,所以while循环内不能用小于<,因为都是地址,地址不能比大小,迭代器的条件都是不等于!=
void test1()
{list<int> lt;lt.push_back(1);lt.push_back(2);lt.push_back(3);lt.push_back(4);list<int>::iterator it = lt.begin();while (it != lt.end()){cout << *it << " ";++it;}cout << endl;
}
反向迭代器
rbegin()就是最后一个元素的下一个位置。
auto rit = lt.rbegin();while (rit != lt.rend()){cout << *rit << " ";++rit;}
构造函数
四个:无参的构造,n个value的构造,迭代器区间构造,拷贝构造。
和vector非常相似不说,查文档。
关于list::sort的排序
如果大量的排序不建议用list自带的。可以用vector进行排序。
对于std算法库里面的sort,需要传随机迭代器才可以使用。
但是list不支持随机访问,list的迭代器是双向迭代器。
list lt;
lt.sort();
对于迭代器实际上分为三类。
1.单向。++ forward_list
2.双向。致辞 ++ – list
3.随机。支持++ – + - vector
所以要求传双向迭代器的,也可以传随机迭代器。
总结:list不支持随机迭代器,他是双向迭代器,不能用库的sort的原因是因为,库里的sort用的快排,快排用的是随机访问,所以一般不用链表进行排序。
解决方法:可以先把数据转移到vector中排序后,再转移到list中。
unique
这个函数的作用是用来去重。
但是去重是有条件的,他只能对排序的list进行去重
list的底层模拟实现
结点类的实现
template<class T>struct list_node{list_node<T>* _next;list_node<T>* _prev;T _data;list_node(const T& val = T()):_next(nullptr), _prev(nullptr), _data(val){}};
迭代器模拟实现
因为底层空间不连续,地址不连续,所以需要封装迭代器
用模板T的原因是迭代器里封装了结点的指针。
版本1
template <class T>
struct _list_iterator
{typedef list_node<T> Node;Node* _node;T& operator*(){return _node->_data;}}
const迭代器,一般写法就是再定义一个const迭代器的类。这样复用性很差。达不到软件工程复用的思想。
大神写法就是用模板参数 来控制。
这里不用管第一个参数T,第一个参数是数据类型,比如int,只用控制解引用和箭头访问数值的就行。也就是控制Ref和 Ptr
const迭代器第一个位置不加const的原因是因为:需要保持一致的类型。因为在begin()函数中用结点的指针构造迭代器时,传递的是int的类型。但是模板传递过去是cosnt int类型。这时候类型不匹配。
//迭代器实现
// typedef __list_iterator<T, T&, T*> iterator;// typedef __list_iterator<T, const T&, const T*> const_iterator;template<class T, class Ref, class Ptr>struct __list_iterator{typedef list_node<T> Node;typedef __list_iterator<T, Ref, Ptr> self;Node* _node;__list_iterator(Node* node):_node(node){}// 析构函数 -- 节点不属于迭代器,不需要迭代器释放// 拷贝构造和赋值重载 -- 默认生成的浅拷贝就可以// *itRef operator*(){return _node->_data;}Ptr operator->(){ //return &(operator*());return &_node->_data;}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(*this);_node = _node->_prev;return tmp;}bool operator!=(const self& it){return _node != it._node;}bool operator==(const self& it){return _node == it._node;}};
list实现
template<class T>class list{typedef list_node<T> Node;public:typedef __list_iterator<T, T&, T*> iterator;typedef __list_iterator<T, const T&, const T*> const_iterator;const_iterator begin() const{// list_node<int>*return const_iterator(_head->_next);}const_iterator end() const{return const_iterator(_head);}iterator begin(){return iterator(_head->_next);//return _head->_next;}iterator end(){return iterator(_head);}list(){_head = new Node();_head->_next = _head;_head->_prev = _head;}// lt2(lt1)/*list(const list<T>& lt){_head = new Node();_head->_next = _head;_head->_prev = _head;for (auto e : lt){push_back(e);}}*/void empty_init(){_head = new Node();_head->_next = _head;_head->_prev = _head;}template <class InputIterator>list(InputIterator first, InputIterator last){empty_init();while (first != last){push_back(*first);++first;}}// 17:00 继续void swap(list<T>& lt){std::swap(_head, lt._head);}// lt2(lt1) -- 现代写法list(const list<T>& lt){empty_init();list<T> tmp(lt.begin(), lt.end());swap(tmp);}// lt2 = lt1list<T>& operator=(list<T> lt){swap(lt);return *this;}~list(){clear();delete _head;_head = nullptr;}void clear(){iterator it = begin();while (it != end()){it = erase(it);}}void push_back(const T& x){//Node* tail = _head->_prev;//Node* newnode = new Node(x); _head tail newnode//tail->_next = newnode;//newnode->_prev = tail;//newnode->_next = _head;//_head->_prev = newnode;insert(end(), x);}void push_front(const T& x){insert(begin(), x);}void pop_back(){erase(--end());}void pop_front(){erase(begin());}// 插入在pos位置之前iterator insert(iterator pos, const T& x){Node* newNode = new Node(x);Node* cur = pos._node;Node* prev = cur->_prev;// prev newnode curprev->_next = newNode;newNode->_prev = prev;newNode->_next = cur;cur->_prev = newNode;return iterator(newNode);}iterator erase(iterator pos){assert(pos != end());Node* cur = pos._node;Node* prev = cur->_prev;Node* next = cur->_next;// prev nextprev->_next = next;next->_prev = prev;delete cur;return iterator(next);}private:Node* _head;};void print_list(const list<int>& lt){list<int>::const_iterator it = lt.begin();while (it != lt.end()){//*it = 10; // 不允许修改cout << *it << " ";++it;}cout << endl;}
插入的实现
只用实现insert就好,头插尾插复用即可。
这个很简单,轻松实现
迭代器失效
insert
list的insert不存在迭代器失效的问题。因为list不需要像vector一样挪动数据,也不像vector一样扩容出现野指针。lsit的每个结点都是独立的。
erase
erase删掉一个结点时,已经delete了,空间已经被释放了。所以会导致迭代器失效。经典野指针失效
所以erase返回删除位置的下一个位置的迭代器。所以需要重新接收迭代器。
析构函数
析构函数内部直接调用clear(),因为析构时指这个结构不要了,所以直接delete哨兵位结点。
void clear()
{iterator it = begin();while(it != end()){it = erase(it);}
}~list()
{clear();delete _head;_head = nullptr;
}
拷贝构造
拷贝构造函数的规则:我们不写,完成浅拷贝。所以_head被拷贝了一份,指向了同一块空间。
浅拷贝不一定有问题,看对应场合,比如在迭代器中,浅拷贝没有错。因为不用析构。
lsit中我们要完成深拷贝。这里需要析构。
这里先用迭代器区间进行拷贝构造
void empty_init()
{_head = new Node();_head ->_next = _head;_head->_prev = _head;
}template <class InputIterator>
list(InputIterator first, InputIterator last)
{//哨兵位结点必须有empty_init();while(first != last){push_pack(*first);++first;}
}
void swap(list<T>& lt)
{std::swap(_head, lt._head);
}
//lt2(lt1)
//现代写法
list(const list<T>& lt)
{empty_init();list<T> tmp(lt.begin(), lt.end());swap(tmp);
}
赋值构造函数
赋值构造函数返回引用,减少拷贝。返回list的原因是支持连续赋值。
//lt2 = lt1;
list<T>& operator=(list<T> lt)
{swap(lt);return *this;
}
相关文章:
植物大战 List——C++
这里写目录标题vector和stirng的细节对于stringlist的使用list的迭代器反向迭代器构造函数关于list::sort的排序uniquelist的底层模拟实现结点类的实现迭代器模拟实现list实现插入的实现迭代器失效inserterase析构函数拷贝构造赋值构造函数vector和stirng的细节 复习vector的深…...
安灯(andon)系统是车间现场管理的必备工具
安灯(andon)系统应用越来越广泛,不单单局限于汽车行业,更多生产型企业意识到了提高工作效率的重要性,提高工作效率根本的能提高生产水平,提高产量,而且安灯(andon)系统不…...
Hazel游戏引擎(004)
本人菜鸟,文中若有代码、术语等错误,欢迎指正 我写的项目地址:https://github.com/liujianjie/GameEngineLightWeight(中文的注释适合中国人的你) 文章目录前言操作步骤讲解GitHubHazel项目此项目定位项目属性修改Sand…...
【CS224W】(task4)图嵌入表示学习
note node2vec: 计算随机游走概率从节点uuu开始模拟rrr条长度为lll的游走链路使用 Stochastic Gradient Descent 优化损失函数 Node2vec在节点分类方面表现更好;而其他方法在链路预测上效果更好,如random walk效率更高;graph emb…...
分享111个HTML医疗保健模板,总有一款适合您
分享111个HTML医疗保健模板,总有一款适合您 111个HTML医疗保健模板下载链接:https://pan.baidu.com/s/1YInaQDnUVsXYtMh1Ls-BHg?pwdxvfc 提取码:xvfc Python采集代码下载链接:采集代码.zip - 蓝奏云 import os import shuti…...
山东大学2022操作系统期末
接力:山东大学2021操作系统期末 2022—2023山东大学计算机操作系统期末考试回忆版 简答题(4 10 points) (1)用户态,核心态是什么 (2)这种区分对现代操作系统的意义 (3)printf(“…...
Hadoop高可用搭建(一)
目录 创建多台虚拟机 修改计算机名称 快速生效 修改网络信息 重启网络服务 关闭和禁用每台机的防火墙 同步时间 安装ntpdate 定时更新时间 启动定时任务 设置集群中每台机器的/etc/hosts 把hosts拷贝发送到每一台虚拟机 配置免密登陆 将本机的公钥拷贝到要免密登…...
算法 - 剑指Offer 重建二叉树
题目 输入某二叉树的前序遍历和中序遍历的结果,请构建该二叉树并返回其根节点。 假设输入的前序遍历和中序遍历的结果中都不含重复的数字。 解题思路 这题较为复杂, 首先审题,前序遍历规则:根左右, 中序遍历&#x…...
手写JavaScript常见5种设计模式
想分享的几种设计模式 目前模式:工厂模式,单例模式,适配器模式,装饰者模式,建造者模式 建造者模式 简介:建造者模式(builder pattern)比较简单,它属于创建型模式的一种…...
Python 异步: 当前和正在运行的任务(9)
我们可以反省在 asyncio 事件循环中运行的任务。这可以通过为当前运行的任务和所有正在运行的任务获取一个 asyncio.Task 对象来实现。 1. 如何获取当前任务 我们可以通过 asyncio.current_task() 函数获取当前任务。此函数将为当前正在运行的任务返回一个任务对象。 ... # …...
REDIS-雪崩、击穿、穿透
直接发车🚗 一.雪崩 1.触发原因 A.大量缓存数据在同一时间过期(失效) B.redis故障宕机 上述均导致全部请求去访问数据库,导致DB压力骤增,严重则导致数据库宕机/系统宕机 2.应对策略 不同触发原因,应对策略也不一致 应对A&a…...
什么人合适学习Python
发了几天的Python基础,也认识了一些朋友,忽然有人问起,说为啥学Python,或者说啥人学习Python,作为一个教龄8年从Python一线讲师到Python教学主管的我和大家分享一下个人的看法,还是提前说一下,个…...
greenDao的使用文档
介绍:greenDAO 是一款轻量级的 Android ORM 框架,将 Java 对象映射到 SQLite 数据库中,我们操作数据库的时候,不在需要编写复杂的 SQL语句, 在性能方面,greenDAO 针对 Android 进行了高度优化, …...
基于JAVA+SpringBoot+LayUI+Shiro的仓库管理系统
基于JAVASpringBootLayUIShiro的仓库管理系统 ✌全网粉丝20W,csdn特邀作者、博客专家、CSDN新星计划导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ 🍅文末获取项目下载方式🍅 一、项…...
金三银四面试必看,复盘字节测试开发面试:一次测试负责人岗位面试总结
最近面试了某企业的测试负责人岗位,历经四面,收获蛮多的。 这篇文章,我想聊聊这次面试过程中的一些经历,以及些许经验和教训。 岗位要求 岗位名称:测试负责人 岗位要求:1、扎实的技术以及丰富的技术项目…...
【算法自由之路】 贪心算法
贪心算法 局部最右得到全局最右难点在于如何证明局部最优可以得到全局最优堆 和 排序 是贪心算法最常用的实现算法 贪心算法作为最符合自然智慧的算法,思路是从小部分取最优从而获得最终的最优,但是难得是怎样获取部分最优才能得到全局最优。 有时候我…...
Scratch少儿编程案例-水果忍者-学生作业
专栏分享 点击跳转=>Unity3D特效百例点击跳转=>案例项目实战源码点击跳转=>游戏脚本-辅助自动化点击跳转=>Android控件全解手册点击跳转=>Scratch编程案例👉关于作者...
7.Docker Compose
Docker Compose 介绍 Docker Compose是Docker官方编排(Orchestration)项目之一,负责快速的部署分布式应用。其代码目前在https://github.com/docker/compose上开源。Compose 定位是 「定义和运行多个 Docker 容器的应用(Definin…...
GitHub访问问题与 Steam++下载及使用(适合小白)
前言 📜 “ 作者 久绊A ” 专注记录自己所整理的Java、web、sql等,IT技术干货、学习经验、面试资料、刷题记录,以及遇到的问题和解决方案,记录自己成长的点滴 目录 前言 一、Steam的介绍 1、大概介绍 2、详细介绍 二、Ste…...
Oracle对象——视图之简单视图与视图约束
文章目录什么是视图为什么会使用视图视图语法案例简单视图的创建更改数据基表,视图数据会变化么?更改视图数据,基表数据会变更么?带检查约束的视图结论创建只读视图(MySQL不支持)总结什么是视图 视图是一种…...
SAP模块常用增强总结
MM模块: 采购订单增强: BADI :ME_GUI_PO_CUST ME_PROCESS_PO_CUST 物料凭证增强: BADI:MB_DOCUMENT_BADI USER-EXIT:MBCF0002 实现功能1、当参照预留过帐时,检查填入数量是否小于预留数量 2…...
当make执行遇到 Arguments too long
1. 问题 Ubuntu20.04上make编译生成so的时候报错: make[1]:execvp:/bin/sh:Arguments too long对应makefile中的报错位置,仅仅是生成so的时候报错,伪代码如下 ${build_tool} -shared -fpic -o "$" ${OBJ_FILE} ${LDFLAGS}然而如…...
《手把手教你》系列基础篇(七十三)-java+ selenium自动化测试-框架设计基础-TestNG实现启动不同浏览器(详解教程)
1.简介 上一篇文章中,从TestNg的特点我们知道支持变量,那么我们这一篇就通过变量参数来启动不同的浏览器进行自动化测试。那么如何实现同时启动不同的浏览器对脚本进行测试,且听我娓娓道来。 2.项目实战 2.1创建一个TestNg class 1.首先按…...
Maven基础
Maven简介 传统项目: jar包不统一 不兼容 项目中有部分jar包会升级 没升级的部分会起冲突 管理复杂 Maven本质是一个项目管理工具 pom POM Project Object Model 项目对象模型 把项目以对象形式进行管理 先写 pom.xml 的配置文件 代表一个项目 1个项目对应1个po…...
C++入门:初识类和对象
C入门:类和对象1 本节目录C入门:类和对象11.auto关键字(C11)1.1类型别名思考1.2auto简介typeid运算符:获取类型信息1.3 auto的使用细则1.4auto不能推到的场景2.基于范围的for循环(C11)2.1范围for的语法2.2范围for的使用条件3.指针…...
BERT在CNN上也能用?看看这篇ICLR Spotlight论文丨已开源
如何在卷积神经网络上运行 BERT?你可以直接用 SparK —— 字节跳动技术团队提出的提出的稀疏层次化掩码建模 ( Designing BERT for Convolutional Networks: Sparse and Hierarchical Masked Modeling ),近期已被人工智能顶会 ICLR 2023 收录为 Spotligh…...
【MFC】模拟采集系统——界面设计(17)
功能介绍 启动界面 开始采集: PS:不涉及 数据保存,重现等功能 界面设计 界面分为三块:顶部黑条带关闭按钮、左边对话框,右边的主界面 资源: 顶部黑条 top.bmp 2* 29 (宽 * 高 像素点&…...
锐捷(十五)mpls vxn跨域optionc场景
一 实验拓扑二 实验需求ce1和ce2为两个分公司,要求两个分公司之间用mpls vxn 进行通信,组网方式是optionc。三 实验分析optionc在转发平面上有点难理解,有一些关键点需要注意,大家点击链接可以参考我上篇发过的一个文章࿱…...
2023备战金三银四,Python自动化软件测试面试宝典合集(七)
马上就又到了程序员们躁动不安,蠢蠢欲动的季节~这不,金三银四已然到了家门口,元宵节一过后台就有不少人问我:现在外边大厂面试都问啥想去大厂又怕面试挂面试应该怎么准备测试开发前景如何面试,一个程序员成长之路永恒绕…...
redis 主从复制
在redis的持久化RDB与AOF详解文章中,我们知道如果redis宕机了,我们可以通过AOF 和 RDB 文件的方式恢复数据,从而保证数据的丢失(或少量损失)从而提高稳定性。但是,如果我们数据只存在一台redis服务器中&…...
网站常用特效/必应收录提交入口
(注意:本文基于API 28的源码分析,API 29上或其他平台的源码略有不同) 前言 当你调用AsyncTask对象的execute()方法时,突然发生崩溃……内心充满不解:java.lang.IllegalStateException: Cannot execute ta…...
网站后台登录ip限制/网站运营主要做什么工作
置信在微软的鼎力推行下,大家都曾经装置了win10系统,但还是防止不了系统变得卡顿的问题,除了一局部是全家桶带来的结果,还有一局部当然是微软自家缘由形成的,所以无论新买的电脑、刚重置完的电脑、还是用久了的电脑&am…...
做国际贸易有哪些平台/优化大师免安装版
2019独角兽企业重金招聘Python工程师标准>>> 两个项目,一个生产者一个消费者,这里只贴出关键代码(队列模式和订阅模式),文章最后会附上项目地址,有需要的可以自行下载。项目访问地址http://loca…...
杭州有哪些做网站的公司/南京市网站
以下是zen cart 首页程序的修改。根据各个文件修改不同的功能。 首页界面://include/templates/zccn/common/tpl_main_page.php首页主样式表://include/templates/zccn/css/schinese_stylesheet.css 首页左边栏目:/includes/templates/templa…...
vr哪家公司做得好/武汉seo网站排名优化公司
通过上一节的学习,我们知道了什么是 ACL 权限,也了解了如何配置linux系统使其开启 ACL 权限,本节来学习 ACL 设定文件访问权限的具体方法。设定 ACl 权限,常用命令有 2 个,分别是setfacl和getfacl命令,前者…...
中国建设银行网站打不开/网络营销的模式有哪些?
为什么我上传一张特定的图片一直是这个异常,但是图片能上传到服务器,save保存方法也没执行成功没插入到数据库中,是不是跟我那个保存方法里面其他东西有关,这个跟图片大小无关,因为上传比它大的图片保存方法都能成功ja…...