[C++入门]---List的使用及模拟实现

文章目录

  • 1.list的介绍
  • 2.list的使用
    • 2.1list的构造函数
    • 2.2list modifiers
    • 2.3list capacity
    • 2.4list elment access
    • 2.5iterator的使用
  • 3.list的模拟实现
    • 3.1list的源码

1.list的介绍

  1. list是可以在常数范围内在任意位置进行插入和删除的序列式容器,并且该容器可以前后双向迭代。
  2. list的底层是双向链表结构,双向链表中每个元素存储在互不相关的独立节点中,在节点中通过指针指向 其前一个元素和后一个元素。
  3. listforward_list非常相似:最主要的不同在于forward_list是单链表,只能朝前迭代,已让其更简单高效。
  4. 与其他的序列式容器相比(arrayvectordeque),list通常在任意位置进行插入、移除元素的执行效率更好。
  5. 与其他序列式容器相比,listforward_list最大的缺陷是不支持任意位置的随机访问,比如:要访问list的第6个元素,必须从已知的位置(比如头部或者尾部)迭代到该位置,在这段位置上迭代需要线性的时间开销;list还需要一些额外的空间,以保存每个节点的相关联信息(对于存储类型较小元素的大list来说这可能是一个重要的因素)

2.list的使用

template < class T, class Alloc = allocator<T> > class list;
//list的使用需要使用显示实例化才能使用

2.1list的构造函数

list (size_type n, const value_type& val = value_type())//构造的list中包含n个值为val的元素
list()//构造空的list
list (const list& x)//拷贝构造函数
list (InputIterator first, InputIterator last)//用[first, last)区间中的元素构造list

eg:

void testlist1()
{list<int> lt1;list<int> lt2(10, 6);for (auto e : lt2){cout << e << " ";}cout<<endl;list<int> lt3(lt2);for (auto e : lt3){cout << e << " ";}cout << endl;list<int> lt4(lt3.begin(), lt3.end());for (auto e : lt4){cout << e << " ";}cout << endl;
}

代码运行结果为:

2.2list modifiers

void push_front (const value_type& val);
//在首元素前插入值为val的元素
void pop_front();
//删除val的第一个元素
void push_back (const value_type& val);
//在list的尾部插入值为val的
void pop_back();
//删除list中最后一个元素
single element (1)	
iterator insert (iterator position, const value_type& val);
//在list position位置插入值为val的元素
fill (2)	void insert (iterator position, size_type n, const value_type& val);
//在list position的位置插入n个值为val的元素
range (3)	
template <class InputIterator>void insert (iterator position, InputIterator first, InputIterator last);
//在list position的位置插入[first,last]区间的元素
iterator erase (iterator position);
//删除position位置的值
iterator erase (iterator first, iterator last);
//删除[first,last)区间的元素
void swap (list& x);
//交换两个list中的元素
void clear();
//清空list中的数据

eg1:

void testlist2()
{list<int> lt1;lt1.push_back(10);lt1.push_back(20);lt1.push_back(30);lt1.push_back(40);lt1.push_back(50);lt1.push_back(60);for (auto& e : lt1){cout << e << " ";}cout << endl;lt1.pop_front();for (auto& e : lt1){cout << e << " ";}cout << endl;lt1.push_front(100);for (auto& e : lt1){cout << e << " ";}cout << endl;lt1.pop_back();for (auto& e : lt1){cout << e << " ";}cout << endl;
}

代码编译运行的结果为:
在这里插入图片描述
eg2:

void testlist3()
{list<int> lt1;lt1.push_back(10);lt1.push_back(20);lt1.push_back(30);lt1.push_back(40);lt1.push_back(50);lt1.push_back(60);list<int>::iterator it = lt1.begin();//在it位置插入99lt1.insert(it, 99);for (auto& e : lt1){cout << e << " ";}cout << endl;it = lt1.begin();//在it位置插入5个6lt1.insert(it, 5, 6);for (auto& e : lt1){cout << e << " ";}cout << endl;it = lt1.begin();list<int> lt2(6, 5);lt1.insert(it, lt2.begin(), lt2.end());for (auto& e : lt1){cout << e << " ";}cout << endl;
}

代码编译运行的结果为:
在这里插入图片描述
eg3:

void testlist4()
{list<int> lt1;lt1.push_back(10);lt1.push_back(20);lt1.push_back(30);lt1.push_back(40);lt1.push_back(50);lt1.push_back(60);list<int>::iterator it = lt1.begin();lt1.erase(it);for (auto& e : lt1){cout << e << " ";}cout << endl;lt1.erase(lt1.begin(), lt1.end());for (auto& e : lt1){cout << e << " ";}cout << endl;
}

代码编译运行的结果为:
在这里插入图片描述
eg4:

void testlist5()
{list<int> lt1;lt1.push_back(10);lt1.push_back(20);lt1.push_back(30);lt1.push_back(40);lt1.push_back(50);lt1.push_back(60);list<int> lt2(5, 6);printf("lt1的当前元素:");for (auto& e : lt1){cout << e << " ";}cout << endl;printf("lt2的当前元素:");for (auto& e : lt2){cout << e << " ";}cout << endl;swap(lt1, lt2);printf("lt1的当前元素:");for (auto& e : lt1){cout << e << " ";}cout << endl;printf("lt2的当前元素:");for (auto& e : lt2){cout << e << " ";}cout << endl;
}

代码编译运行的结果为:
在这里插入图片描述
eg5:

void testlist6()
{list<int> lt1;lt1.push_back(10);lt1.push_back(20);lt1.push_back(30);lt1.push_back(40);lt1.push_back(50);lt1.push_back(60);for (auto& e : lt1){cout << e << " ";}cout << endl;//清空lt1原有数据后插入66lt1.clear();lt1.push_back(66);for (auto& e : lt1){cout << e << " ";}cout << endl;
}

代码编译运行的结果为:
在这里插入图片描述

2.3list capacity

bool empty() const;
//检测list是否为空,是返回true,否则返回false
size_type size() const;
//返回list中有效节点的个数

2.4list elment access

reference front();
const_reference front() const;
//返回list的第一个节点中值的引用
reference back();
const_reference back() const;
//返回list的最后一个节点中值的引用

eg1:

void testlist7()
{list<int> lt1;lt1.push_back(10);lt1.push_back(20);lt1.push_back(30);lt1.push_back(40);lt1.push_back(50);lt1.push_back(60);cout << "list头部元素为:" << lt1.front() << endl;cout << "list尾部元素为:" << lt1.back() << endl;	
}

代码运行的结果为:
在这里插入图片描述

2.5iterator的使用

iterator begin();
const_iterator begin() const;
//返回第一个元素的迭代器
iterator end();
const_iterator end() const;
//返回最后一个元素下一个位置的迭代器
reverse_iterator rbegin();
const_reverse_iterator rbegin() const;
//返回第一个元素的reverse_iterator,即end位置
reverse_iterator rend();
const_reverse_iterator rend() const;
//返回最后一个元素下一个位置的reverse_iterator,即begin位置

list容器使用迭代器

void testlist8()
{list<int> lt1(5, 6);list<int>::iterator it = lt1.begin();	while (it != lt1.end()){cout << *it <<" ";it++;}cout << endl;
}

代码运行的结果为:
在这里插入图片描述
迭代器分类:

input iterator//输入迭代器
output iterator//输出迭代器
forward iterator//单向迭代器可以++ 适用forward_list/unorderd_xxx容器
bidirectional iterator//双向迭代器可以++/-- 适用list/map/set容器
random access iteartor//任意迭代器可以++/--/+/- 适用于vector/string/deque容器

在这里插入图片描述

随机迭代器可以使用双向迭代器,反之双向迭代器不可以使用随机迭代器!较多功能的容器迭代器可以使用适配较少功能的迭代器的算法接口函数,反之则不可以!

栗子:
list的迭代器为:
在这里插入图片描述
算法接口函数为:
在这里插入图片描述
在这里插入图片描述

void testlist9()
{list<int> lt1;lt1.push_back(16);lt1.push_back(8);lt1.push_back(99);lt1.push_back(18);lt1.push_back(36);lt1.push_back(6);//不可以使用algorithm//sort(lt1.begin(), lt1.end());//可以使用list自己的sort进行排序lt1.sort();for (auto& e : lt1){cout << e << " ";}cout << endl;
}

代码编译运行的结果为:
在这里插入图片描述

list的迭代器为双向迭代器,不能使用算法接口函数中适配任意迭代器的sort函数,只能使用list的sort函数

3.list的模拟实现

3.1list的源码

#pragma once
#include<iostream>
using namespace std;
namespace newspace
{template<class T>struct list_node{list_node<T>* _prev;list_node<T>* _next;T _val;list_node(const T& val = T()):_prev(nullptr), _next(nullptr), _val(val){}};template<class T,class Ref,class Ptr>struct __list_iterator{typedef list_node<T> Node;Node* _node;typedef __list_iterator<T, Ref, Ptr> self;__list_iterator(Node* node):_node(node){}Ref operator*(){return _node->_val;}Ptr operator->(){return &_node->_val;}//__list_iterator<T,Ref,Ptr>& operator++()self& operator++(){_node = _node->_next;return *this;}__list_iterator<T, Ref, Ptr> operator++(int)//self operator++(int){//__list_iterator<T, Ref, Ptr> tmp(*this);self tmp(*this);_node = _node->_next;return tmp;}__list_iterator<T, Ref, Ptr>& operator--()//self& operator--(int){_node = _node->_prev;return *this;}//__list_iterator<T, Ref, Ptr> operator--(int)self operator--(int){//__list_iterator<T, Ref, Ptr> tmp(*this);self tmp(*this);_node = _node->_prev;return tmp;}bool operator==(const __list_iterator<T, Ref, Ptr>& it){return _node == it._node;}bool operator!=(const __list_iterator<T, Ref, Ptr>& it){return _node != it._node;}};//template<class T>//struct __list_const_iterator//{//	typedef list_node<T> Node;//	Node* _node;//	__list_const_iterator(Node* node)//		:_node(node)//	{}//	const T& operator*()//	{//		return _node->_val;//	}//	__list_const_iterator<T>& operator++()//	{//		_node = _node->_next;//		return *this;//	}//	__list_const_iterator<T>& operator++(int)//	{//		__list_const_iterator<T> tmp(*this);//		_node = _node->_next;//		return *this;//	}//	bool operator==(const __list_const_iterator<T>& it)//	{//		return _node == it._node;//	}//	bool operator!=(const __list_const_iterator<T>& it)//	{//		return _node != it._node;//	}//};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;//这样设计太冗余了//typedef __list_const_iterator<T> const_iterator;//这样设计const迭代器是不行的,因为const迭代器期望修饰内容不被修改//这样设计迭代器本身不能修改//typedef const _list_iterator<T> const_iterator;//如何设计const对象的iterator//const T* ptr1;//ptr1本身不能修改//T* const ptr2;//ptr2指向的内容不能修改iterator begin(){return _head->_next;}iterator end(){return _head;}const_iterator begin()const{return _head->_next;}const_iterator end()const{return _head;}void empty_init(){_head = new Node;_head->_prev = _head;_head->_next = _head;_size = 0;}//构造函数list(){empty_init();}list(const list<T>& lt){empty_init();for (auto& e : lt){push_back(e);}}void swap(list<T>& lt){std::swap(_head, lt._head);std::swap(_size, lt._size);}const list<T>& operator=(list<T> lt){swap(lt);return *this;}void clear(){if (_head != nullptr){iterator it = begin();while (it != end()){it = erase(it);}_size = 0;}}~list(){clear();delete _head;_head = nullptr;_size = 0;}//void push_back(const T& x)//{//	Node* tail = new Node(x);//	tail->_prev = _head->_prev;//	tail->_prev->_next = tail;//	_head->_prev = tail;//	tail->_next = _head;//}void push_back(const T& x){//Node* tail = _head->_prev;//Node* newnode = new Node(x);//newnode->_prev = tail;//tail->_next = newnode;//_head->_prev = newnode;//newnode->_next = _head;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* cur = pos._node;Node* prev = cur->_prev;Node* newnode = new Node(x);prev->_next = newnode;newnode->_prev = prev;newnode->_next = cur;cur->_prev = newnode;++_size;return newnode;}//删除pos位置的数据iterator erase(iterator pos){assert(pos != end());Node* cur = pos._node;Node* prev = cur->_prev;Node* next = cur->_next;prev->_next = next;next->_prev = prev;--_size;delete cur;return next;}size_t size()const{//const_iterator it = begin();//size_t size = 0;//while (it != end())//{//	size++;//	it++;//}//return size;return _size;}private:Node* _head;size_t _size;};

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

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

相关文章

【数据结构】堆排序详解

文章目录 一、堆排序思想二、向上调整建堆排序三、向下调整建堆排序四、总结 对于什么是堆&#xff0c;堆的概念分类以及堆的向上和向下两种调整算法可见&#xff1a; 堆的创建 一、堆排序思想 int a[] { 2,3,5,7,4,6 };对于这样一个数组来说&#xff0c;要想要用堆排序对它…

java.lang.ClassCastException: android.os.BinderProxy cannot be cast to ...

项目开发遇到下面这个报错了&#xff01; 问题原因 直接说原因&#xff0c;就是因为进程间不能直接传递对象&#xff0c;应该传递该Binder对象的映射&#xff08;代理对象&#xff09;&#xff0c;所以类型转换就出错了。如果在同一个进程中&#xff0c;直接传递对象没有关系&a…

9月15日作业

Qt代码 #include "mywnd.h"//构造函数的定义 mywnd::mywnd(QWidget *parent): QWidget(parent) //显性调用父类的有参构造完成对子类从父类继承下来成员的初始化工作 {//窗口设置this->resize(QSize(500, 433));this->setWindowTitle("Widget&quo…

安装GPU驱动,CUDA Toolkit和配置与CUDA对应的Pytorch

如果有帮助,记得回来点个赞 目录 1.安装指定GPU驱动如果安装的GPU CUDA Version和CUDA Toolkit版本已经冲突怎么办? 2.安装指定版本的CUDA Toolkit如果我安装了CUDA Toolkit之后nvcc -V仍然显示旧的CUDA Toolkit版本怎么办? 3.安装与CUDA对应的Pytorch已经安装了错乱版本的c…

《C++ primer plus》精炼(OOP部分)——对象和类(4)

“学习是人类进步的阶梯&#xff0c;也是个人成功的基石。” - 罗伯特肯尼迪 文章目录 友元函数利用友元函数重载<<运算符重载部分示例&#xff1a;矢量类 友元函数 先看看在上一章中我们作为例子的代码&#xff1a; class Student{string name;int grade;int operator…

第十九章、【Linux】开机流程、模块管理与Loader

19.1.1 开机流程一览 以个人计算机架设的 Linux 主机为例&#xff0c;当你按下电源按键后计算机硬件会主动的读取 BIOS 或 UEFI BIOS 来载入硬件信息及进行硬件系统的自我测试&#xff0c; 之后系统会主动的去读取第一个可开机的设备 &#xff08;由 BIOS 设置的&#xff09; …

如何实现wingftpserver部署到外网访问?快解析p2p内网穿透

不少朋友选择用wing FTP来搭建部署FTP服务管理文件共享。Wing FTP Server是一个跨平台ftp服务器端&#xff0c;它有不错的可靠性和一个友好的配置界面&#xff0c;Wing FTP Server除了能提供FTP的基本服务功能以外&#xff0c;还能提供管理员终端、任务计划、基于Web的管理端和…

中国智能客服发展历程

中国智能客服的发展历程&#xff1a; 在2000年以前&#xff0c;互联网尚未普及&#xff0c;客服主要以电话沟通为主。从2000年到2010年&#xff0c;得益于计算机技术、计算机电话集成技术&#xff08;CTI&#xff09;、网络技术、多媒体机技术以及CRM、BI、ERP、OA等企业信息化…

基于SSM+Vue的校园教务系统的设计与实现

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SSM 前端&#xff1a;采用Vue技术开发 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#x…

MATLAB入门-字符串操作

MATLAB入门-字符串操作 注&#xff1a;本篇文章是学习笔记&#xff0c;课程链接是&#xff1a;link MATLAB中的字符串特性&#xff1a; 无论是字符还是字符串&#xff0c;都要使用单引号来‘’表示&#xff1b;在MATLAB中&#xff0c;字符都是在矩阵中存储的&#xff0c;无论…

Leetcode: 645.错误的集合 题解【超详细】

题目 集合 s 包含从 1 到 n 的整数。不幸的是&#xff0c;因为数据错误&#xff0c;导致集合里面某一个数字复制了成了集合里面的另外一个数字的值&#xff0c;导致集合 丢失了一个数字 并且 有一个数字重复 。 给定一个数组 nums 代表了集合 S 发生错误后的结果。 请你找出重复…

新手如何开始Microstation CE版二次开发

一步步学习MicroStation CE MDL&#xff08;C&#xff09;开发 - 技术资料库 - Bentley 中国优先社区 - Bentley Communities https://communities.bentley.com/communities/other_communities/chinafirst/w/chinawiki/57704/microstation-ce-mdl-c一步步学习MicroStation CE A…

算法:合并两个有序数组---双指针[1]

文章来源&#xff1a; https://blog.csdn.net/weixin_45630258/article/details/132673462 欢迎各位大佬指点、三连 1、题目&#xff1a; 给你两个按 非递减顺序 排列的整数数组 nums1 和 nums2&#xff0c;另有两个整数 m 和 n &#xff0c;分别表示 nums1 和 nums2 中的元…

小节5:Python列表list常用操作

1、对列表的基本认知&#xff1a; 列表list&#xff0c;是可变类型。比如&#xff0c;append()函数会直接改变列表本身&#xff0c;往列表里卖弄添加元素。所以&#xff0c;list_a list_a.append(123)就是错误的。如果想删除列表中的元素&#xff0c;可以用remove()函数&…

Android RecyclerView BaseSectionQuickAdapter实现分组功能

详情网站&#xff1a;手把手教你使用BaseSectionQuickAdapter实现分组功能&#xff0c;史上最详细Adapter使用教程_basequickadapter 分组_杨阿程的博客-CSDN博客 //加入二个包implementation com.android.support:recyclerview-v7:26.0.0-beta1implementation com.github.Cym…

2023/9/15 -- C++/QT

作业&#xff1a; 1> 将工程文件进行注释 2> 03login_box.pro: QT core gui #core核心库 gui图形开发库greaterThan(QT_MAJOR_VERSION, 4): QT widgets #4.0版本以上自动包含widgets库CONFIG c11 #支持C11版本# The following define makes your compiler em…

深度学习推荐系统(八)AFM模型及其在Criteo数据集上的应用

深度学习推荐系统(八)AFM模型及其在Criteo数据集上的应用 1 AFM模型原理及其实现 沿着特征工程自动化的思路&#xff0c;深度学习模型从 PNN ⼀路⾛来&#xff0c;经过了Wide&#xff06;Deep、Deep&#xff06;Cross、FNN、DeepFM、NFM等模型&#xff0c;进⾏了大量的、基于不…

idea装载jerbel以及文件上传下载

一、JRebel 1.1 Jrebel介绍 JRebel是一个Java开发工具&#xff0c;它是一款用于实时代码重载的插件。它的主要功能是在不重新启动应用程序的情况下&#xff0c;将修改后的Java代码实时应用到正在运行的应用程序中&#xff0c;从而加快开发周期&#xff0c;提高开发效率。 实…

Sqlserver如何调试存储过程

前提&#xff1a;需要使用Sql Server Managerment Studio 工具进行调试。 步骤&#xff1a; 1.选择存储过程&#xff0c;右键选择“执行存储过程”。操作过后&#xff0c;会生成一个调用存储过程的代码块。 2.以编辑模式打开所以需要调试的存储过程。 3.点击调试按钮进行调…

【视觉检测】电源线圈上的导线弯直与否视觉检测系统软硬件方案

 检测内容 线圈上的导线弯直与否检测系统。  检测要求 检测线圈上的导线有无弯曲&#xff0c;弯曲度由客户自己设定。检测速度5K/8H625PCS/H。  视觉可行性分析 对样品进行了光学实验&#xff0c;并进行图像处理&#xff0c;原则上可以使用机器视觉进行测试测量…