C++入门篇9---list

list是带头双向循环链表

一、list的相关接口及其功能

1. 构造函数

函数声明功能说明
list(size_type n,const value_type& val=value_type())构造的list中包含n个值为val的元素
list()构造空的list
list(const list& x)拷贝构造
list(InputIterator first, InputIterator last)[fiirst,last)区间的元素构造list
void test1()
{list<int> v;list<int> v1(5,2);list<int> v2(v1);list<int> v3(v1.begin(),v1.end());for (auto x : v)cout << x << " ";cout << endl;for (auto x : v1)cout << x << " ";cout << endl;for (auto x : v2)cout << x << " ";cout << endl;for (auto x : v3)cout << x << " ";cout << endl;}

 2.list的迭代器

函数名称功能名称
begin()+end()获取第一个数据位置的iterator/const_iterator,获取最后一个数据的下一个位置的iterator/const_iterator
rbegin()+rend()获取第一个数据位置的reverse_iterator/const_reverse_iterator,获取最后一个数据的下一位置的reverse_iterator/const_reverse_iterator

 

void test2()
{list<int> v;v.push_back(1);v.push_back(2);v.push_back(3);v.push_back(4);list<int>::iterator it = v.begin();//注意如果写类型名,那么一定要写正确,如加不加reverse、const一定要写对//如果不想写这么长的类型,可以写auto自动类型推导while (it != v.end()){cout << *it << " ";it++;}cout << endl;list<int>::reverse_iterator it1 = v.rbegin();while (it1 != v.rend()){cout << *it1 << " ";it1++;}cout << endl;
}

3.list的capacity

函数声明功能介绍
empty()检测list是否为空
size()返回list中有效结点的个数

 4.获取首尾元素

函数声明功能介绍
front返回list的第一个节点中值的引用
back返回list的最后一个结点中值的引用

5.list的修改

函数名称功能介绍
push_front在list首元素前插入值为val的值
pop_front删除list中第一个元素
push_back在list尾部插入值为val的值
pop_back删除list中的最后一个元素
insert在list中pos位置插入值为val的元素
erase删除list中pos位置的元素
swap交换两个list中的元素
clear清空list中的有效元素
void test3()
{list<int> v;v.push_back(1);v.push_back(2);v.push_back(3);v.push_back(4);v.push_front(1);v.push_front(2);v.push_front(3);v.push_front(4);for (auto x : v)cout << x << " ";cout << endl;v.pop_back();v.pop_front();for (auto x : v)cout << x << " ";cout << endl;v.insert(v.begin(),10);for (auto x : v)cout << x << " ";cout << endl;v.erase(v.begin());for (auto x : v)cout << x << " ";cout << endl;
}

 6.list迭代器失效问题(重点

在讲vector的博客中,我也提到了迭代器失效问题,那么问个问题,list的迭代器失效和vector的迭代器失效一样吗?为什么?

这里先解释一下什么是迭代器,估计有很多人对这个名词还不是很了解,其实所谓的迭代器从作用上来说就是访问遍历容器的工具,它将所有容器的访问遍历方式进行了统一(vector,list,set等等容器的迭代器使用几乎一摸一样都是begin(),end(),++/--等操作),封闭了底层的细节,简化了我们对容器的使用,对于初学者来说,这玩意tm的太神了,但是如果我们了解它的底层实现,我们就会发现,迭代器不过是一层封装,底层还是数据结构那一套,如list链表,迭代器的++,本质还是指针的变化。

(容器的底层实现还是要了解一些,能够帮助我们更好的认识和使用容器,可以看看我写过的一些模拟实现,如果有需要注释或者详解,请在评论区留言,如果需求多,我会单独出一篇博客讲解一下里面的一些重点内容)

好,下面回归正题,如果你数据结构学的还不错并且知道vector的迭代器失效是扩容引起的,那么这个问题不难回答,因为链表的增查改不会影响一个结点的位置,除了删除操作,所以list的迭代器失效仅仅只有在删除list结点时才会出现,并且只有那个被删除结点的迭代器会失效,其他的不受影响

二、模拟实现list的基本功能

namespace zjs
{template <class T>struct list_node {T _data;list_node<T>* _next;list_node<T>* _prev;list_node(const T& data = T()):_data(data),_next(nullptr),_prev(nullptr){}};//重点template <class T, class Ref, class Ptr >struct __list_iterator {typedef list_node<T> Node;typedef __list_iterator self;Node* node;__list_iterator(Node* x):node(x){}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;}Ref operator*(){return node->_data;}bool operator==(const self& It) const{return node == It.node;}bool operator!=(const self& It) const{return node != It.node;}Ptr operator->(){return &node->_data;}};/*template <class T>struct __list_const_iterator {typedef list_node<T> Node;typedef __list_const_iterator self;Node* node;__list_const_iterator(Node* x):node(x){}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;}const T& operator*() {return node->_data;}const T* operator->(){return &node->_data;}bool operator==(const self& It){return node == It.node;}bool operator!=(const self& It){return node != It.node;}};*/template <class T>class list{public:typedef list_node<T> Node;typedef __list_iterator<T, T&, T*> iterator;typedef __list_iterator<T,const T&,const T*> const_iterator;//typedef __list_const_iterator<T> const_iterator;void empty_init(){_head = new Node;_head->_next = _head;_head->_prev = _head;}list(){_size = 0;empty_init();}void clear(){iterator it = begin();while (it!=end()){it = erase(it);}}~list(){clear();delete _head;_head = nullptr;}list(const list<T>& tmp):_head(nullptr),_size(0){empty_init();for (auto& x : tmp){push_back(x);}}void swap(list& tmp){std::swap(_head, tmp._head);std::swap(_size, tmp._size);}list<T>& operator=(list<T> tmp){swap(tmp);return *this;}const_iterator begin() const{return _head->_next;}iterator begin(){//return iterator(_head->_next);return _head->_next;}const_iterator end() const{//return iterator(_head);return _head;}iterator end(){//return iterator(_head);return _head;}void push_back(const T& x){//Node* tail = _head->_prev;//Node* newnode = new Node(x);//tail->_next = newnode;//newnode->_prev = tail;//newnode->_next = _head;//_head->_prev = newnode;insert(end(), x);}void push_front(const T& x){insert(begin(), x);}iterator insert(iterator pos, const T& x){Node* cur = pos.node;Node* pre = cur->_prev;Node* newnode = new Node(x);pre->_next = newnode;newnode->_prev = pre;newnode->_next = cur;cur->_prev = newnode;_size++;return newnode;}void pop_back(){erase(--end());}void pop_front(){erase(begin());}iterator erase(iterator pos){Node* cur = pos.node;Node* pre = cur->_prev;Node* next = cur->_next;pre->_next = next;next->_prev = pre;delete cur;_size--;return next;}size_t size() const{return _size;}private:Node* _head;size_t _size;};//模板的一些应用,typename的用法//这里只能用typedef,用来告诉编辑器const_iterator是一个类型名,而不是一个静态变量//因为编辑器在编译阶段要判断有没有语法错误,而list<T>没有实例化,就无法在里面//查找const_iterator,而如果它是静态变量很显然这是个语法错误,//所以这里要加上typename告诉编辑器这是个类型名,等到实例化之后再去里面找template<typename T>void print_list(const list<T>& s){typename list<T>::const_iterator it = s.begin();while (it != s.end()){cout << *it << " ";++it;}cout << endl;}template<typename container>void print_container(const container& s){typename container::const_iterator it = s.begin();while (it != s.end()){cout << *it << " ";++it;}cout << endl;}}

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

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

相关文章

Python爬虫——scrapy_当当网图书管道封装

创建爬虫项目 srcapy startproject scrapy_dangdang进入到spider文件里创建爬虫文件&#xff08;这里爬取的是青春文学&#xff0c;仙侠玄幻分类&#xff09; srcapy genspider dang http://category.dangdang.com/cp01.01.07.00.00.00.html获取图片、名字和价格 # 所有的se…

快速通过华为HCIP认证

你可以按照以下步骤进行准备和学习&#xff1a; 华为认证课程和资料--提取码:1234https://pan.baidu.com/s/1YJhD8QbocHhZ30MvrKm8hg 了解认证要求&#xff1a;查看华为官方网站上的HCIP认证要求和考试大纲&#xff0c;了解考试的内容、考试形式和考试要求。 学习相关知识&am…

c++ std::shared_ptr(内存布局)

https://cplusplus.com/reference/memory/shared_ptr/

AIGC绘画:kaggle部署stable diffusion项目绘画

文章目录 kaggle介绍项目部署edit my copy链接显示 结果展示 kaggle介绍 Kaggle成立于2010年&#xff0c;是一个进行数据发掘和预测竞赛的在线平台。从公司的角度来讲&#xff0c;可以提供一些数据&#xff0c;进而提出一个实际需要解决的问题&#xff1b;从参赛者的角度来讲&…

泛微E-Office任意文件上传漏洞复现

0x01 产品简介 泛微E-Office是一款标准化的协同 OA 办公软件&#xff0c;泛微协同办公产品系列成员之一,实行通用化产品设计&#xff0c;充分贴合企业管理需求&#xff0c;本着简洁易用、高效智能的原则&#xff0c;为企业快速打造移动化、无纸化、数字化的办公平台。 0x02 漏…

【Linux】Reactor模式

Reactor模式 Reactor模式的定义 Reactor反应器模式&#xff0c;也叫做分发者模式或通知者模式&#xff0c;是一种将就绪事件派发给对应服务处理程序的事件设计模式。 Reactor模式的角色构成 Reactor主要由以下五个角色构成&#xff1a; reactor模式的角色 角色解释Handle(句…

TIA博途_通过EXCEL快速给PLC程序段添加注释信息的方法示例

通过EXCEL快速给PLC程序段添加注释信息的方法示例 如下图所示,以OB1为例,正常情况下,我们可以在博途中直接输入各个程序段的注释信息, 但是如果程序段较多的话,逐个输入的话效率不高,此时可以参考下面这种通过EXCEL进行快速添加的方法。 如下图所示,选中某个OB或FC、FB块…

线性代数再回顾

最近&#xff0c;在深度学习线性代数&#xff0c;之前大一的时候学过线性代数&#xff0c;但那纯属于是应试用的&#xff0c;考试一考完&#xff0c;啥都忘了&#xff0c;也说出不出个所以然&#xff0c;所以&#xff0c;在B站的MIT的线性代数以及3blue1brown线性代数的本质中去…

Vim学习(二)—— 编译C程序

打开终端&#xff0c;这里以MobaXterm为例&#xff0c; 邮件创建新的空文件并命名&#xff0c; 然后cd到对应路径下&#xff0c;用 vim hello.cvim打开创建的文件&#xff0c;进入编辑模式&#xff0c;编辑完程序后按Esc退出编辑模式&#xff0c;输入 :wq保存并退出&#xf…

uniapp微信小程序消息订阅快速上手

一、微信公众平台小程序开通消息订阅并设置模板 这边的模板id和详细内容后续前后端需要使用 二、uniapp前端 需要是一个button触发 js&#xff1a; wx.getSetting({success(res){console.log(res)if(res.authSetting[scope.subscribeMessage]){// 业务逻辑}else{uni.request…

Linux下如何修改CPU 电源工作模式

最近处理一起历史遗留问题&#xff0c;感觉很爽。 现象&#xff1a; 背景&#xff1a;设备采用ARM&#xff0c;即rk3568处理器&#xff0c;采用Linux系统&#xff1b;主要用于视觉后端处理 现象&#xff1a;当软件运行一段时间&#xff0c;大概1个小时&#xff08;也不是很固定…

对话 4EVERLAND:Web3 是云计算的新基建吗?

在传统云计算的发展过程中&#xff0c;数据存储与计算的中心化问题&#xff0c;对用户来说一直存在着潜在的安全与隐私风险——例如单点故障可能会导致网络瘫痪和数据泄露等危险。同时&#xff0c;随着越来越多 Web3 项目应用的落地&#xff0c;对于数据云计算的性能要求也越来…

Kotlin runBlocking launch多个协程读写mutableListOf时序

Kotlin runBlocking launch多个协程读写mutableListOf时序 import kotlinx.coroutines.delay import kotlinx.coroutines.launch import kotlinx.coroutines.runBlockingfun main(args: Array<String>) {var lists mutableListOf<String>()runBlocking {launch {r…

《零基础7天入门Arduino物联网-05》电路基础知识下

配套视频课程&#xff1a;《零基础学Arduino物联网&#xff0c;入门到进阶》 配套课件资料获取&#xff1a;微联实验室 配套学习套件购买&#xff1a;淘宝搜索店铺【微联实验室】 电阻、电容、电感和二极管 电阻 电阻用于电路中&#xff0c;其主要功能在于控制电流的流动和阻…

R语言实现非等比例风险生存资料分析(1)

#非等比例风险的生存资料分析 ###1 生成模拟数据### library(flexsurv) set.seed(123) # 生成样本数量 n <- 100 # 生成时间数据 time <- sample(1:1000,n,replaceF) # 调整shape和scale参数以控制生存曲线形状 # 生成事件数据&#xff08;假设按比例风险模型&#xff0…

GitHub 如何部署写好的H5静态页面

感谢粉皮zu的私信&#xff0c;又有素材写笔记了。(●’◡’●) 刚好记录一下我示例代码的GitHub部署配置&#xff0c;以便于后期追加仓库。 效果 环境 gitwin 步骤 第一步 新建仓库 第二步 拉取代码 将仓库clone到本地 git clone 地址第三步 部署文件 新建.github\workflo…

设计模式之原型模式Prototype的C++实现

1、原型模式提出 在软件功能设计中&#xff0c;经常面临着“某些结构复杂的对象”的创建工作&#xff0c;且创建的对象想拥有其他对象在某一刻的状态&#xff0c;则可以使用原型模型。原型模型是通过拷贝构造函数来创建对象&#xff0c;并且该对象拥有其他对象在某一刻的状态。…

知识体系总结(九)设计原则、设计模式、分布式、高性能、高可用

文章目录 架构设计为什么要进行技术框架的设计 六大设计原则一、单一职责原则二、开闭原则三、依赖倒置原则四、接口分离原则五、迪米特法则&#xff08;又称最小知道原则&#xff09;六、里氏替换原则案例诠释 常见设计模式构造型单例模式工厂模式简单工厂工厂方法 生成器模式…

【深入理解Linux内核锁】三、原子操作

我的圈子: 高级工程师聚集地 我是董哥,高级嵌入式软件开发工程师,从事嵌入式Linux驱动开发和系统开发,曾就职于世界500强企业! 创作理念:专注分享高质量嵌入式文章,让大家读有所得! 文章目录 1、原子操作思想2、整型变量原子操作2.1 API接口2.2 API实现2.2.1 原子变量结…

LVS-DR模式

目录 1、概述 2、LVS-DR模式的工作原理&#xff1a; 3、在LVS-DR模式下&#xff0c;数据包的流向分析如下&#xff1a; 4、LVS-DR是一种用于构建高可用性负载均衡集群的技术模式。LVS-DR模式具有以下特点&#xff1a; 5、LVS-DR中的ARP问题 6、配置LVS-DR需要以下几个关键…