模拟实现list超详解(C++)

在这里插入图片描述

😇 😇各位小伙伴们,大家好!我是bug。今天我们继续学习STL容器中的list:
(代码可能会有一点问题,请各位老铁指正 😘 😘 )

一、list的概念

🍉 🍉list:在C++中list容器是双向带头循环链表,这种结构在数据的插入删除上相比于vector有着极大的优势,其时间复杂度为O(1)。它唯一的缺点就是不支持随机访问,去查找数据只能够通过遍历的方式,而vector可以通过下标进行访问。

二、list的用法

🌹 🌹list的常用接口:

construct(构造函数) 用法
list() 构造空list
list (size_type n, const value_type& val = value_type()) 构造包含n个数据为val的list
list (const list& x) 拷贝构造函数
list (InputIterator first, InputIterator last) 用[first, last)区间中的元素构造list
遍历操作 用法
begin 返回第一个元素的iterator
end 返回最后一个元素下一个位置的iterator
rbegin 返回第一个元素的reverse_iterator
rend 返回最后一个元素下一个位置的reverse_iterator
操作空间/容量 用法
empty 检测list是否为空,是返回true,否则返回false
size 返回list中有效节点的个数
获得数据 用法
front 返回list的第一个节点中值的引用
back 返回list的最后一个节点中值的引用
修改操作 用法
push_front 在list首元素前插入值为val的元素
pop_front 删除list中第一个元素
push_back 在list尾部插入值为val的元素
pop_back 删除list中最后一个元素
insert 在list position 位置中插入值为val的元素
erase 删除list position位置的元素
swap 交换两个list中的元素
clear 清空list中的有效元素

🌳(1)list对象的创建

list创建对象的方式有很多,比如:
🌵 使用默认构造函数
🌵 使用带参构造函数
🌵 使用拷贝构造函数
🌵 使用赋值运算符重载
🌵 使用迭代器区间进行构造
🌵 创建匿名对象

🍒 🍒代码⬇️ ⬇️:

	//无参构造
	list<int> lt1;
	//有参数构造
	list<int> lt2(4, 5);
	//迭代器区间进行构造
	llist<int> lt3(lt2.begin(), lt2.end());
	//拷贝构造
	list<int> lt4(lt3);
	//赋值运算符重载
	list<int> lt5 = lt4;

🌳(2)list的遍历

与vector、string不同,list由于空间不连续,不支持用[]进行访问数据。所以list的遍历方式只有迭代器和范围for两种。

🍒 🍒代码⬇️ ⬇️:

	list<int> lt1(4,5);
	//迭代器进行遍历
	list<int>::iterator it = lt1.begin();
	while (it != lt1.end())
	{
   
		cout << *it << " ";
		it++;
	}
	cout << endl;

	//范围for进行遍历
	for (auto e : lt1)
	{
   
		cout << e << " ";
	}
	cout << endl;

🌳(3)迭代器失效问题****

在list中插入并不存在迭代器失效的问题,因为list的插入不会改变它原有的空间。但是list的删除会造成迭代器失效,而且失效的部分是指向了被删除的空间迭代器,其他部分的迭代器不会有所影响。

和vector一样,erase使用了返回新迭代器的方式来避免失效。

注意❗️ ❗️

迭代器有两种实现方式,具体应根据容器底层数据结构实现:

🍔1. 原生态指针,比如:vector的迭代器就是原生态指针
🍔 2. 将原生态指针进行封装,因迭代器使用形式与指针完全相同,因此在自定义的类中必须实现以下方法:

🍁1、指针解引用,重载operator*()
🍁 2、 指针->访问其所指空间成员,重载oprator->()
🍁3.、指针可以++向后移动,迭代器类中必须重载operator++()与operator++(int)至于operator–()/operator–(int)释放需要重载,根据具体的结构来抉择,双向链表可以以向前 移动,所以需要重载,如果是forward_list就不需要重载。
🍁4、 迭代器需要进行是否相等的比较,因此还需要重载operator==()与operator!=()

三、list的模拟实现

🍒 🍒这里我们来实现一个简易的vector⬇️ ⬇️:

//结点
		_Tp _data;
		_list_node<_Tp>* _next;
		_list_node<_Tp>* _prev;

		//构造函数
		_list_node(const _Tp& val = _Tp())
		
//迭代器
		typedef _list_node<_Tp>  Link_type;
		typedef _list_iterator<_Tp, Ref,Ptr>  self;
		//引用
		typedef Ref reference;
		typedef const Ref const_reference;
		//指针
		typedef Ptr pointer;
		typedef const Ptr const_pointer;
		
		//构造函数
		_list_iterator(Link_type* pnode = nullptr)
		_list_iterator(const self& lt)
		
		//重载
		reference operator*()
		pointer operator->() 
		const_reference operator*()const
		const_pointer operator->()const
		bool operator!=(const self& x)const
		bool operator==(const self& x)const
		self& operator++() 
		self operator++(_Tp) 
		self& operator--()
		self operator--(_Tp) 
		
//list
		
  • 39
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 29
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 29
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

今天也要写bug

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值