C++入门--list

news2024/12/22 19:42:38

目录

list的介绍:

list的构造:

遍历:

reverse、sort、unique

list的模拟实现:

反向迭代器:

list与vector的比较:


list的介绍:

list是序列容器,允许在序列内的任何位置执行O(1)的插入和删除操作,以及双向迭代。

list的构造:

void TestList1()
{
    list<int> l1;                         // 构造空的l1
    list<int> l2(4, 10);                  // 4个10
    list<int> l3(l2.begin(), l2.end());   // 用l2的[begin(), end())构造l3
    list<int> l4(l3);                     // 用l3拷贝构造l4

    // 以数组为迭代器区间构造l5
    int arr[] = { 16,2,77,29 };
    list<int> l5(arr, arr + sizeof(arr) / sizeof(int));

    // 列表格式初始化C++11
    list<int> l6{ 1, 2, 3, 4, 5 };
}

遍历:

list只能通过迭代器和范围for进行遍历,不支持下标访问。

void test_list2()
{
	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;

	list<int>::reverse_iterator rit = lt.rbegin();
	while (rit != lt.rend())
	{
		cout << *rit << " ";
		++rit;
	}
	cout << endl;

	for (auto e : lt)
	{
		cout << e << " ";
	}
	cout << endl;
}

 reverse、sort、unique(有序,去重)

void test_list2()
{
	list<int> lt;
	lt.push_back(1);
	lt.push_back(3);
	lt.push_back(3);
	lt.push_back(2);
	lt.push_back(4);

	lt.sort();                //排序

	lt.reverse();            //逆置

	lt.unique();            //去重(有序)
}

list的模拟实现:

    List 的迭代器是将原生指针进行封装,把节点指针放到迭代器类中,对迭代器类进行运算符重载,就可以像顺序容器的指针一样进行访问和修改

namespace qwe
{
	template<class T>
	struct ListNode
	{
		ListNode<T>* _next;
		ListNode<T>* _prev;
		T _data;

		ListNode(const T& data = T())
			:_next(nullptr)
			, _prev(nullptr)
			, _data(data)
		{}
	};
	          //   T         T&        T*
	template<class T, class Ref, class Ptr>
	struct __list_iterator
	{
		typedef ListNode<T> Node;
		typedef __list_iterator<T, Ref, Ptr> self;

		Node* _node;

		__list_iterator(Node* x)
			:_node(x)
		{}

		Ref operator*()
		{
			return _node->_data;
		}

		Ptr operator->()
		{
			return &_node->_data;
		}

		//++it
		self& operator++()
		{
			_node = _node->_next;
			return *this;
		}

		//it++
		self operator++(int)
		{
			self tmp(*this);
			_node = _node->_next;
			return tmp;
		}

		//--it
		self operator--()
		{
			_node = _node->_prev;
			return *this;
		}

		//it--
		self operator--(int)
		{
			self tmp(*this);
			_node = _node->_prev;
			return tmp;
		}

		bool operator!=(const self& it)const
		{
			return _node != it._node;
		}

		bool operator==(const self& it)const
		{
			return _node == it._node;
		}
	};

	template<class T>
	class list
	{
		typedef ListNode<T> Node;
	public:
		typedef __list_iterator<T, T&, T*> iterator;
		typedef __list_iterator<T, const T&, const T*> const_iterator;

		typedef reverse_iterator<const_iterator, const T&, const T* > const_reverse_iterator;
		typedef reverse_iterator<iterator, T&, T*> reverse_iterator;

		reverse_iterator rbegin()
		{
			return reverse_iterator(end());
		}

		reverse_iterator rend()
		{
			return reverse_iterator(begin());
		}

		iterator begin()
		{
			return iterator(_head->_next);
		}

		iterator end()
		{
			return iterator(_head);
		}

		const_iterator begin()const
		{
			return const_iterator(_head->_next);
		}

		const_iterator end()const
		{
			return const_iterator(_head);
		}

		list()
		{
			_head = new Node();
			_head->_next = _head;
			_head->_prev = _head;
		}

		//list<Date> lt1(5, Date(2022, 1, 11));
		//list<int> lt2(5, 1)
		list(int n, const T& val = T())
		{
			_head = new Node();
			_head->_next = _head;
			_head->_prev = _head;
			for (int i = 0; i < n; ++i)
			{
				push_back(val);
			}
		}

		list(size_t n, const T& val = T())
		{
			_head = new Node();
			_head->_next = _head;
			_head->_prev = _head;
			for (size_t i = 0; i < n; ++i)
			{
				push_back(val);
			}
		}

		template<class InputIterator>
		list(InputIterator first, InputIterator last)
		{
			_head = new Node();
			_head->_next = _head;
			_head->_prev = _head;
			while (first != last)
			{
				push_back(*first);
				++first;
			}
		}

		//lt2(lt1)
		list(const list<T>& lt)
		{
			_head = new Node();
			_head->_next = _head;
			_head->_prev = _head;

			list<T> tmp(lt.begin(), lt.end());
			std::swap(_head, tmp._head);
		}

		//lt2 = lt1
		list<T>& operator=(list<T> lt)
		{
			std::swap(_head, lt._head);
			return *this;
		}

		~list()
		{
			clear();

			delete _head;
			_head = nullptr;
		}

		void clear()
		{
			iterator it = begin();
			while (it != end())
			{
				erase(it++);
			}
		}

		void push_front(const T& x)
		{
			insert(begin(), x);
		}

		void push_back(const T& x)
		{
			insert(end(), x);
		}

		void pop_back()
		{
			erase(--end());
		}

		void pop_front()
		{
			erase(begin());
		}

		//insert,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;

			return iterator(newnode);
		}

		//erase,pos一定失效
		iterator erase(iterator pos)
		{
			assert(pos != end());

			Node* prev = pos._node->_prev;
			Node* next = pos._node->_next;
			delete pos._node;
			prev->_next = next;
			next->_prev = prev;

			return iterator(next);
		}
	private:
		Node* _head;
	};

	void print_list(const list<int>& lt)
	{
		list<int>::const_iterator it = lt.begin();
		while (it != lt.end())
		{
			cout << *it << " ";
			++it;
		}
		cout << endl;
	}

	void test_list1()
	{
		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())
		{
			*it *= 2;
			cout << *it << " ";
			++it;
		}
		cout << endl;

		print_list(lt);
	}

	struct Date
	{
		int _year;
		int _month;
		int _day;

		Date(int year = 1, int month = 1, int day = 1)
			:_year(year)
			, _month(month)
			, _day(day)
		{}
	};

	void test_list2()
	{
		list<Date> lt;
		lt.push_back(Date(2001, 1, 11));
		lt.push_back(Date(2001, 2, 11));
		lt.push_back(Date(2001, 3, 11));

		list<Date>::iterator it = lt.begin();
		while (it != lt.end())
		{
			cout << (*it)._year << " ";
			cout << it->_year << " ";

			++it;
		}
		cout << endl;
	}

	void test_list3()
	{
		list<int> lt1;
		lt1.push_back(1);
		lt1.push_back(2);
		lt1.push_back(3);

		list<int> lt2(lt1);
		for (auto e : lt2)
		{
			cout << e << " ";
		}
		cout << endl;

		list<int> lt3;
		lt3.push_back(10);
		lt3.push_back(10);
		lt3.push_back(10);
		lt3.push_back(10);

		lt1 = lt3;
		for (auto e : lt1)
		{
			cout << e << " ";
		}
		cout << endl;
	}

	void test_list4()
	{
		list<Date> lt1(5, Date(2022, 1, 1));
		for (auto e : lt1)
		{
			cout << e._year << " ";
		}
		cout << endl;

		list<int> lt2(5, 1);
		for (auto e : lt2)
		{
			cout << e << " ";
		}
		cout << endl;
	}

	void test_list5()
	{
		list<int> lt1;
		lt1.push_back(1);
		lt1.push_back(2);
		lt1.push_back(3);
		lt1.push_back(4);

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

		list<int>::reverse_iterator rit = lt1.rbegin();
		while (rit != lt1.rend())
		{
			cout << *rit << " ";
			++rit;
		}
		cout << endl;
	}
}

  反向迭代器:

        反向迭代器的++就是正向迭代器的--,所以,反向迭代器内部可以包含一个正向迭代器,对正向迭代器的接口进行包装即可。
namespace qwe
{
	template<class Iterator, class Ref, class Ptr>
	class reverse_iterator
	{
		typedef reverse_iterator<Iterator, Ref, Ptr>self;
	public:
		reverse_iterator(Iterator it)
			:_it(it)
		{}

		Ref operator*()
		{
			Iterator prev = _it;
			return *--prev;
		}

		Ptr operator->()
		{
			return &operator*();
		}

		self& operator++()
		{
			--_it;
			return *this;
		}

		self& operator--()
		{
			++_it;
			return *this;
		}

		bool operator!=(const self& rit)const
		{
			return _it != rit._it;
		}

	private:
		Iterator _it;
	};
}

list与vector的比较:

                              vector                      list
底 层 结 构
动态顺序表,一段连续的物理空间
带头结点的双向循环链表
随机访问
支持随机访问,访问某个元素效率O(1)
不支持随机访问,访问某个元素
效率O(N)
插入和删除
任意位置插入和删除效率低,时间复杂 度O(N),插入时有可能需要增容,增容:开辟新空间,拷贝元素,释放旧空间,导致效率更低
任意位置插入和删除效率高,时间复杂度为 O(1)
空间利用率
底层为连续空间,不容易造成内存碎片,空间利用率 高,缓存命中率高
底层节点动态开辟,小节点容易
造成内存碎片,空间利用率低,
缓存命中率低
迭代器
原生指针
对节点指针进行封装
迭代器失效
插入元素有可能会导致重新扩容,致使原来迭代器失效,删除时,如果不考虑缩容,原来迭代器指向的内容改变导致失效
插入元素不会导致迭代器失效,
删除元素时,只会导致当前迭代
器失效,其他迭代器不受影响
使用场景
需要高效存储,支持随机访问,不关心插入删除效率
大量插入和删除操作,不关心随
机访问

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

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

相关文章

RocketMQ源码(19)—Broker处理DefaultMQPushConsumer发起的拉取消息请求源码【一万字】

基于RocketMQ release-4.9.3&#xff0c;深入的介绍了Broker处理DefaultMQPushConsumer发起的拉取消息请求源码。 此前我们学习了RocketMQ源码(18)—DefaultMQPushConsumer消费者发起拉取消息请求源码。我们知道consumer在发送了拉取消息请求的时候&#xff0c;请求的Code为PUL…

【 JavaScript编程详解 -1 】什么是JavaScript ?

文章目录简介Java与JavaScript的不同Javascrpt可以做什么JavaScript的构成为什么可以在浏览器中运行如何将 JavaScript 代码添加到网站&#xff1f;方法1- \<script\>标签内嵌JavaScript方法1- \<script\>标签引入外部JavaScript文件方法3- 内联 JavaScript编辑器推…

蛇形矩阵(简单明了的方法)

T112524 【数组2】蛇形矩阵 题目来源 AC代码 #include<stdio.h>int main() {int arr[111][111];int n 0;scanf("%d",&n);int temp 0;int sum 1;while(temp<(2*n-2)){for(int i0;i<n;i){for(int j0;j<n;j){if((ij) temp){if(temp%2 0){arr[…

基于FPGA的时间数字转换(TDC)设计(三)

1.多相位TDC计时测试 以下为多相位TDC计时的测试。图1为多相位TDC计时的测试框图,利用信号发生器,产生两路同相位、具有固定延时的脉冲信号,一路作为Start信号,另外一路作为Stop信号。由于分辨率为312.5ps,因此以312.5ps为步进,对Stop信号进行延时,扫描一个周期,通过UA…

红米 12C earth Fastboot 线刷包 root TWRP 刷入magisk recovery卡刷

红米 12C earth Fastboot 线刷包 root TWRP 刷入magisk recovery卡刷 红米 12C (earth) 国行版 Fastboot 线刷包 & Recovery 卡刷包 ROM 红米 12C earth Fastboot 线刷包 root TWRP 刷入magisk recovery卡刷下载 红米 12C 稳定版 Fastboot 线刷包 要安装国行版 红米 12C F…

对笔试使用《剑指offer》吧(第十天)

跟着博主一起刷题 这里使用的是题库&#xff1a; https://leetcode.cn/problem-list/xb9nqhhg/?page1 目录剑指 Offer 62. 圆圈中最后剩下的数字剑指 Offer 64. 求12…n剑指 Offer 65. 不用加减乘除做加法剑指 Offer 62. 圆圈中最后剩下的数字 剑指 Offer 62. 圆圈中最后剩下的…

【BP靶场portswigger-客户端12】跨站点请求伪造CSRF-12个实验(全)

前言&#xff1a; 介绍&#xff1a; 博主&#xff1a;网络安全领域狂热爱好者&#xff08;承诺在CSDN永久无偿分享文章&#xff09;。 殊荣&#xff1a;CSDN网络安全领域优质创作者&#xff0c;2022年双十一业务安全保卫战-某厂第一名&#xff0c;某厂特邀数字业务安全研究员&…

YOLO家族系列模型的演变:从v1到v8(上)

YOLO V8已经在本月发布了&#xff0c;我们这篇文章的目的是对整个YOLO家族进行比较分析。了解架构的演变可以更好地知道哪些改进提高了性能&#xff0c;并且明确哪些版本是基于那些版本的改进&#xff0c;因为YOLO的版本和变体的命名是目前来说最乱的&#xff0c;希望看完这篇文…

Android 深入系统完全讲解(18)

3 su Root 的相关代码原理 在 Android4.4 的时候&#xff0c;我们经常能够看到 Root Apk&#xff0c;作为发烧友操作这个才算是真的会 Android。那么学习 su 的代码&#xff0c;就是非常有意义的事情。这一节来说下 su 是如何管理权限 的&#xff0c;如何调用授权 Apk&#xf…

撒贝宁搭档某网红,直播带货人气破十万,央视主持人能接私活吗

随着互联网的发展&#xff0c;直播已经司空见惯&#xff0c;直播带货更是成为家常便饭&#xff0c;尤其是那些有了名气的人。就在不久前&#xff0c;央视著名主持人撒贝宁&#xff0c;也开启了自己的直播带货首秀&#xff0c;不得不说央视主持人还是多才多艺。 在很短时间内&am…

SpringBoot 自定义拦截器

SpringBoot 自定义拦截器 目录SpringBoot 自定义拦截器一、自定义拦截器二、编写控制器三、添加拦截器对象&#xff0c;注入到容器的配置类中另一种写法四、最后application运行一、自定义拦截器 创建登录拦截器 com/bjpowernode/springbootinterceptor02/interceptor LoginI…

改进YOLOv7系列:结合丰富的梯度流信息模块,来自YOLOv8的核心模块

&#x1f4a1;统一使用 YOLOv7 代码框架&#xff0c;结合不同模块来构建不同的YOLO目标检测模型。&#x1f31f;本项目包含大量的改进方式,降低改进难度,改进点包含【Backbone特征主干】、【Neck特征融合】、【Head检测头】、【注意力机制】、【IoU损失函数】、【NMS】、【Loss…

【Linux操作系统】进程优先级和进程切换

文章目录一.进程优先级1.三段论谈优先级2.PRI和NI二.进程切换1.进程的四个特性2.上下文数据保护和恢复一.进程优先级 1.三段论谈优先级 什么是优先级&#xff1f;它等同于权限吗&#xff1f; 定义: cpu资源分配的先后顺序&#xff0c;就是指进程的优先权&#xff08;priority…

SpringBoot + MDC 实现全链路调用日志跟踪

写在前面MDC介绍MDC使用MDC 存在的问题解决MDC存在的问题写在前面通过本文将了解到什么是MDC、MDC应用中存在的问题、如何解决存在的问题基于 Spring Boot MyBatis Plus Vue & Element 实现的后台管理系统 用户小程序&#xff0c;支持 RBAC 动态权限、多租户、数据权限、…

Shader踩坑笔记UV操作

一、UV坐标范围0-1 // 坐标范围 0-1&#xff0c;原点在画布左下角 vec2 uv FRAGCOORD.xy / iResolution.xy; 有两个变量 1、FRAGCOORD是godot引擎自带的变量表示纹理坐标 2、iResolution我自定义的变量&#xff0c;输入画布尺寸 使用uniform关键词可以创建自定义变量 比…

戴尔电脑怎么录屏?这6个方法教你轻松录屏

无论您是需要录制屏幕活动以创建在线发布的演示文稿、录制网络研讨会的屏幕以供日后参考&#xff0c;还是出于任何其他原因——如果您使用的是戴尔或类似 PC&#xff0c;您有多种选择。那么&#xff0c;让我们来谈谈如何在戴尔笔记本电脑上进行屏幕记录。 在戴尔笔记本电脑上录…

机器人介绍、应用、前景

机器人介绍、应用、前景1 介绍1.1 定义1.2 作用1.3 发展历程1.4 分类1.5 三大顾虑1.6 前景2 种类工业机器臂协作机械臂工业移动机器人复合机器人扫地机器人服务机器人机器狗人形机器人无人机3 技术3.1 机器人学分类3.2 功能分类3.2.1 感知3.2.2 决策3.2.3 执行AGV减震机构减速机…

经典问题:Python实现生产者消费者模式的多线程爬虫

Python实现生产者消费者模式的多线程爬虫1. 多组件的Pipeline技术架构2. 生产者消费者爬虫的架构3.多线程数据通信的queue.Queue4. 代码编写实现生产者消费者爬虫1. 多组件的Pipeline技术架构 复杂的事情一般都不会一下子做完&#xff0c;而是会分很多中间步骤一步步完成。 …

二十七、Kubernetes中DaemonSet(DS)控制器详解

1、概述 在kubernetes中&#xff0c;有很多类型的pod控制器&#xff0c;每种都有自己的适合的场景&#xff0c;常见的有下面这些&#xff1a; ReplicationController&#xff1a;比较原始的pod控制器&#xff0c;已经被废弃&#xff0c;由ReplicaSet替代 ReplicaSet&#xff…

LeetCode题目笔记——2293. 极大极小游戏

文章目录题目描述题目难度——简单方法一&#xff1a;模拟代码/Python方法二&#xff1a;优化本地修改代码/python代码/C总结题目描述 给你一个下标从 0 开始的整数数组 nums &#xff0c;其长度是 2 的幂。 对 nums 执行下述算法&#xff1a; 设 n 等于 nums 的长度&#x…