STL---list

目录

1. list的介绍及使用

1.1 list的介绍

1.2 list的使用注意事项

2.list接口介绍及模拟实现

2.1构造​编辑

2.2容量

2.3修改

3.list迭代器

4.迭代器失效

5.模拟实现

6.vector和list的区别


1. list的介绍及使用

1.1 list的介绍

list的文档介绍

1. list是可以在常数范围内在任意位置进行插入和删除的序列式容器,并且该容器可以前后双向迭代。

2. list的底层是带头双向循环链表结构,双向链表中每个元素存储在互不相关的独立节点中,在节点中通过指针指向其前一个元素和后一个元素。

3. list与forward_list非常相似:最主要的不同在于forward_list是单链表,只能朝前迭代,已让其更简单高效。

4. 与其他的序列式容器相比(array,vector,deque),list通常在任意位置进行插入、移除元素的执行效率更好。

5. 与其他序列式容器相比,list和forward_list最大的缺陷是不支持任意位置的随机访问,比如:要访问list的第6个元素,必须从已知的位置(比如头部或者尾部)迭代到该位置,在这段位置上迭代需要线性的时间开销;list还需要一些额外的空间,以保存每个节点的相关联信息(对于存储类型较小元素的大list来说这可能是一个重要的因素)

1.2 list的使用注意事项

1.list不支持随机访问,不能使用[ ]来访问元素。

2.list.sort()使用的是归并排序,默认为升序,如果需要排降序

// 降序
list<int> lt;
greater<int> it;
lt.sort(it);

//匿名对象
lt.sort(greater<int> ());

但是使用list的sort排序效率不是很高,在处理数据量较多的情况下,可以将数据拷贝到vector中,再使用vector.sort(),再将数据拷贝回去。

list<int> lt;

vector<int> v(lt.begin(), lt.end());
sort(v.begin(), v.end());
lt.assign(v.begin(), v.end());

2.list接口介绍及模拟实现

2.1构造

void empty_init()
{
	head = new Node;
	head->next = head;
	head->prev = head;

	_size = 0;
}

list()
{
	empty_init();
}

list(const list& lt)
{
	empty_init();
	for (auto e : lt)
	{
		push_back(e);
	}
}

2.2容量

bool empty()
{
	return head->next == head;
}

size_t size()
{
	return _size;
}

2.3修改

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

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

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

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

void insert(iterator pos, const T& value = T())
{
	Node* cur = pos._node;
	Node* prev = cur->prev;
	Node* newnode = new Node(value);

	prev->next = newnode;
	newnode->prev = prev;
	newnode->next = cur;
	cur->prev = newnode;

	++_size;
}

iterator erase(iterator pos)
{
	Node* cur = pos._node;
	Node* prev = cur->prev;
	Node* next = cur->next;

	prev->next = next;
	next->prev = prev;

	delete cur;
	--_size;

	return next;
}

void swap(list<T>& lt)
{
	std::swap(lt.head);
	std::swap(lt.size);
}

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

3.list迭代器

与vector和string不同,list的迭代器需要自己实现,list迭代器可以理解为一个指针,指向list中的某个结点,而链表的每个结点在物理空间上并不连续,所以当迭代器++的时候,并不能直接到下一个结点的位置,并且*的时候,并不知道访问的是链表中的哪个数据,所以我们需要自己实现,将迭代器进行封装。

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)
	{}

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

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

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

	self& operator--()
	{
		_node = _node->prev;
		return *this;
	}

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

需要注意的是,类模板参数有三个,是为了同时能实现迭代器和const迭代器,在list类中直接传不同的参数即可。

4.迭代器失效

此处大家可将迭代器暂时理解成类似于指针,迭代器失效即迭代器所指向的节点的无效,即该节点被删除了。因为list的底层结构为带头结点的双向循环链表,因此在list中进行插入时是不会导致list的迭代器失效的,只有在删除时才会失效,并且失效的只是指向被删除节点的迭代器,其他迭代器不会受到影响。

void TestListIterator1()
{
    int array[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
    list<int> l(array, array+sizeof(array)/sizeof(array[0]));

    auto it = l.begin();
    while (it != l.end())
    {
        // erase()函数执行后,it所指向的节点已被删除,因此it无效,在下一次使用it时,必须先给其赋值
        l.erase(it);
        ++it;
    }
}

//修改

void TestListIterator()
{
    int array[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
    list<int> l(array, array+sizeof(array)/sizeof(array[0]));

    auto it = l.begin();
    while (it != l.end())
    {
        it = l.erase(it);
    }
}

5.模拟实现

namespace cola
{
	template<class T>
	struct _list_node
	{
		T date;
		_list_node<T>* next;
		_list_node<T>* prev;

		_list_node(const T& value = T())
			: date(value)
			, next(nullptr)
			, prev(nullptr)
		{}
	};

	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)
		{}

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

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

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

		self& operator--()
		{	
			_node = _node->prev;
			return *this;
		}

		self operator++(int)
		{
			self temp(*this);
			_node = _node->next;
			return temp;
		}

		self operator--(int)
		{
			self temp(*this);
			_node = _node->prev;
			return temp;
		}

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

		bool operator==(const self& lt)
		{
			return _node == lt._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;

		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->next = head;
			head->prev = head;

			_size = 0;
		}

		list()
		{
			empty_init();
		}

		~list()
		{
			clear();
			delete head;
		}

		list(const list& lt)
		{
			empty_init();
			for (auto e : lt)
			{
				push_back(e);
			}
		}

		list& operator=(const list& lt)
		{
			if (head != lt.head)
			{
				clear();
				for (auto e : lt)
				{
					push_back(e);
				}
			}

			return *this;
		}

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

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

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

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

		void insert(iterator pos, const T& value = T())
		{
			Node* cur = pos._node;
			Node* prev = cur->prev;
			Node* newnode = new Node(value);

			prev->next = newnode;
			newnode->prev = prev;
			newnode->next = cur;
			cur->prev = newnode;

			++_size;
		}

		iterator erase(iterator pos)
		{
			Node* cur = pos._node;
			Node* prev = cur->prev;
			Node* next = cur->next;

			prev->next = next;
			next->prev = prev;

			delete cur;
			--_size;

			return next;
		}

		void swap(list<T>& lt)
		{
			std::swap(lt.head);
			std::swap(lt.size);
		}

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

		bool empty()
		{
			return head->next == head;
		}

		size_t size()
		{
			return _size;
		}

	private:
		Node* head;
		size_t _size;
	};

    
    //打印函数(适用于任何容器)
	template<typename Container>
	void print_container(const Container& lt)
	{
		typename Container::const_iterator it = lt.begin();
		while (it != lt.end())
		{
			cout << *it << " ";
			++it;
		}

		cout << endl;
	}
}

6.vector和list的区别

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

回归预测 | MATLAB实现BES-LSSVM秃鹰搜索算法优化最小二乘支持向量机多输入单输出回归预测(多指标,多图)

回归预测 | MATLAB实现BES-LSSVM秃鹰搜索算法优化最小二乘支持向量机多输入单输出回归预测&#xff08;多指标&#xff0c;多图&#xff09; 目录 回归预测 | MATLAB实现BES-LSSVM秃鹰搜索算法优化最小二乘支持向量机多输入单输出回归预测&#xff08;多指标&#xff0c;多图&a…

探索智能文字识别:技术、应用与发展前景

探索智能文字识别&#xff1a;技术、应用与发展前景 前言一张图全览大赛作品解读随心记你不对我对小结 智能文字识别体系化解读图像预处理文字定位和分割文字区域识别图像校正字体识别和匹配结果后处理小结 如何应对复杂场景下挑战复杂场景应对方法小结 人才时代对人才要求合合…

Facebook AI mBART:巴别塔的硅解

2018年&#xff0c;谷歌发布了BERT&#xff08;来自transformers的双向编码器表示&#xff09;&#xff0c;这是一种预训练的语言模型&#xff0c;在一系列自然语言处理&#xff08;NLP&#xff09;任务中对SOTA结果进行评分&#xff0c;并彻底改变了研究领域。类似的基于变压器…

Linux 上 离线部署GeoScene Server Py3 运行时环境

默认安装ArcGIS Pro的时候&#xff0c;会自动部署上Python3环境&#xff0c;所以在windows上不需要考虑这个问题&#xff0c;但是linux默认并不部署Py3&#xff0c;因此需要单独部署&#xff0c;具体部署可以参考Linux 上 ArcGIS Server 的 Python 3 运行时—ArcGIS Server | A…

亚马逊买家怎么留评

亚马逊买家可以按照以下步骤在购买后留下产品评价&#xff1a; 1、登录亚马逊账户&#xff1a;首先&#xff0c;在网页浏览器中打开亚马逊网站&#xff0c;登录你的亚马逊账户。 2、找到订单&#xff1a;在页面上找到并点击你购买过的商品的"我的订单"或"订单…

手机自动无人直播,实景无人直播真的有用吗?

继数字人直播之后&#xff0c;手机自动直播开始火热了起来&#xff0c;因为其门槛低&#xff0c;成本低&#xff0c;一部手机一个账号就可以实现直播&#xff0c;一时深受广大商家的好评。那么&#xff0c;手机自动无人直播究竟是如何实现自动直播的呢&#xff1f; 在传统的直…

Dockerfile快速搭建自己专属的LAMP环境

目录 编写Dockerfile 1.文件内容需求&#xff1a; 2.值得注意的是centos6官方源已下线&#xff0c;所以需要切换centos-vault源&#xff01; 3.Dockerfile内容 4.进入到 lamp 开始构建镜像 推送镜像到私有仓库 1.创建用户并添加到私有仓库&#xff1a;​编辑​编辑 2.推…

万宾科技22款产品入选《城市生命线安全工程监测技术产品名录》

2023年8月17日-18日&#xff0c;由北京市地下管线协会主办的2023首届城市生命线安全与发展大会在北京召开&#xff0c;本次大会汇聚中央及地方政府主管领导、院士专家、行业领袖、龙头代表、产业精英等。 大会聚焦安全监管智慧平台和燃气爆炸、城市内涝、地下管线交互风险、第三…

【云原生,k8s】Helm应用包管理器介绍

目录 一、为什么需要Helm&#xff1f; &#xff08;一&#xff09;Helm介绍 &#xff08;二&#xff09;Helm有3个重要概念&#xff1a; &#xff08;三&#xff09;Helm特点 二、Helm V3变化 &#xff08;一&#xff09;架构变化 &#xff08;二&#xff09;自动创建名…

R语言处理缺失数据(1)-mice

#清空 rm(listls()) gc()###生成模拟数据### #生成100个随机数 library(magrittr) set.seed(1) asd<-rnorm(100, mean 60, sd 10) %>% round #平均60&#xff0c;标准差10 #将10个数随机替换为NA NA_positions <- sample(1:100, 10) asd[NA_positions] <- NA #转…

SpringBoot + MyBatisPlus中乐观锁的实现 (精简demo)

乐观锁加注解Version后不需要手动进行加1操作。乐观锁是一种用于解决并发冲突的机制&#xff0c;在数据库中用于保护数据的一致性。Version注解是MyBatisPlus框架中的乐观锁注解&#xff0c;它会在更新数据时自动检查版本号是否一致&#xff0c;如果一致则进行更新操作&#xf…

ClickHouse(二十一):Clickhouse SQL DDL操作-临时表及视图

进入正文前&#xff0c;感谢宝子们订阅专题、点赞、评论、收藏&#xff01;关注IT贫道&#xff0c;获取高质量博客内容&#xff01; &#x1f3e1;个人主页&#xff1a;含各种IT体系技术&#xff0c;IT贫道_Apache Doris,大数据OLAP体系技术栈,Kerberos安全认证-CSDN博客 &…

Python功能制作之简单的3D特效

需要导入的库&#xff1a; pygame: 这是一个游戏开发库&#xff0c;用于创建多媒体应用程序&#xff0c;提供了处理图形、声音和输入的功能。 from pygame.locals import *: 导入pygame库中的常量和函数&#xff0c;用于处理事件和输入。 OpenGL.GL: 这是OpenGL的Python绑定…

奥威BI数据可视化工具:360度呈现数据,告别枯燥表格

随着企业数据量的不断增加&#xff0c;如何有效地进行数据分析与决策变得越来越重要。奥威BI数据可视化工具作为一款强大的数据分析工具&#xff0c;在帮助企业深入挖掘数据价值方面具有显著优势。 奥威BI数据可视化工具是一款基于数据仓库技术的数据分析工具&#xff0c;具有…

07-微信小程序-注册页面-模块化

07-微信小程序-注册页面 文章目录 注册页面使用 Page 构造器注册页面参数Object初始数据案例代码 生命周期回调函数组件事件处理函数setData()案例代码 生命周期模块化 注册页面 对于小程序中的每个页面&#xff0c;都需要在页面对应的 js 文件中进行注册&#xff0c;指定页面…

Leetcode-每日一题【剑指 Offer 34. 二叉树中和为某一值的路径】

题目 给你二叉树的根节点 root 和一个整数目标和 targetSum &#xff0c;找出所有 从根节点到叶子节点 路径总和等于给定目标和的路径。 叶子节点 是指没有子节点的节点。 示例 1&#xff1a; 输入&#xff1a;root [5,4,8,11,null,13,4,7,2,null,null,5,1], targetSum 22输…

Newsprk Newspaper新闻报纸WordPress主题

Newsprk Newspaper新闻报纸WordPress主题对于任何使用 WordPress 技术构建的新闻和杂志网站来说都是一个有吸引力且时尚的主题。Newsprk – 报纸 WordPress 主题非常适合任何新闻/杂志或与以下类别匹配的任何特定业务&#xff0c;如博客、体育、时尚、科学、足球、政治、视频、…

利用Jackson封装常用的JsonUtil工具类

在实际开发中&#xff0c;我们对于 JSON 数据的处理&#xff0c;通常有这么几个第三方工具包可以使用&#xff1a; gson&#xff1a;谷歌的fastjson&#xff1a;阿里巴巴的jackson&#xff1a;美国FasterXML公司的&#xff0c;Spring框架默认用的 由于以前一直用习惯了阿里的…

多维时序 | MATLAB实现PSO-CNN-BiGRU多变量时间序列预测

多维时序 | MATLAB实现PSO-CNN-BiGRU多变量时间序列预测 目录 多维时序 | MATLAB实现PSO-CNN-BiGRU多变量时间序列预测预测效果基本介绍模型描述程序设计参考资料 预测效果 基本介绍 1.多维时序 | MATLAB实现PSO-CNN-BiGRU多变量时间序列预测&#xff1b; 2.运行环境为Matlab20…

无涯教程-PHP - sql_regcase()函数

sql_regcase() - 语法 string sql_regcase (string string) 可以将sql_regcase()函数视为实用程序函数&#xff0c;它将输入参数字符串中的每个字符转换为包含两个字符的带括号的表达式。 sql_regcase() - 返回值 返回带括号的表达式字符串以及转换后的字符。 sql_regcase…