【C++】list模拟实现

额额额,浅学了list,老规矩,模拟实现一下list,能让我们更好的理解list。若有兴趣,不妨垂阅!

目录

1.模拟实现list 

1.1.list节点

1.2.list正向迭代器 

 1.3.list模拟实现

2. test

3.小知识 

 3.1.小知识1

3.2.小知识2

3.3.小知识3

3.4.小知识4

4.模拟实现list完整代码


同样的,我不可能把list所有接口都模拟实现出来,我也没有这个能力。So,模拟实现一些简单常用的接口。

本工程包括2个文件:

mylist.h:用于模拟实现list。

test.cpp:用于测试模拟实现的list接口是否达到预期。

1.模拟实现list 

以下代码均放到mylist.h文件中。 

1.1.list节点

 由于list底层是带头(哨兵位)双向循环链表。所以模拟实现的list节点需要能找到前驱节点和后继节点,这点是毋庸置疑的。那么,我们将list节点设计如下:

namespace HD
{
	//list节点
	template<typename T>
	struct listNode
	{
		typedef listNode node;//类里面可以将listNode<T>用listNode替代
		T _val;
		node* _prev;
		node* _next;
	};
}

_val用于存储数据,_prev用于指向前驱节点,_next用于指向后继指针。

1.2.list正向迭代器 

 好的,由于list反向迭代器较为复杂,所以我只模拟实现正向迭代器。正向迭代器分为:普通正向迭代器、const正向迭代器。一个一个来模拟实现:


1.普通正向迭代器

我们知道迭代器是模拟指针的行为,但是却不是所有的迭代器都能直接用原生指针实现。例如:

string的正向迭代器,由于其底层是字符顺序表,可以直接用原生指针来实现迭代器;

但是如list底层是链表,正向迭代器就不能直接用原生指针实现,好比如,list<int>::iterator it; ++it;,如果该list的正向迭代器是原生指针实现的,++操作能让it指向下一个节点吗?显然不能,因为链表的物理空间不是连续的。

那么我们怎么办?

别忘了操作符重载这里利器,我们可以用类封装一下原生指针来实现普通正向迭代器:

namespace HD
{
    //list 普通正向迭代器
	template <typename T>
	struct listIterator
	{
		typedef listNode<T>* pNode;
		typedef listIterator<T> self;
		pNode _pNode;

		listIterator<T>(pNode pNode = nullptr)
			:_pNode(pNode)
		{

		}
		T& operator*()
		{
			return (*_pNode)._val;
		}
		self operator++(int)//后置++
		{
			self it(_pNode);
			_pNode = _pNode->_next;
			return it;
		}
		self& operator++()//前置++
		{
			_pNode = _pNode->_next;
			return *this;
		}
		self operator--(int)//后置--
		{
			self it(_pNode);
			_pNode = _pNode->_prev;
			return it;
		}
		self& operator--()//前置--
		{
			_pNode = _pNode->_prev;
			return *this;
		}
		bool operator!=(const self& it)
		{
			return _pNode != it._pNode;
		}
		bool operator==(const self& it)
		{
			return _pNode == it._pNode;
		}
		T* operator->()
		{
			return &_pNode->_val;
		}
	};
}

其实仔细看,这个类只有一个成员变量,就是list节点的指针_pNode。把这个指针用类封装一下,提供各种运算符重载作为该类的成员函数,就成了。本质上,这个类不还是list节点指针吗?但是这个list节点指针的行为却不是原生指针的行为能达到的。。。。。好好体会!!!! 


2.const正向迭代器 

普通正向迭代器和const正向迭代器基本一样。我们想想,const正向迭代器区别于普通正向迭代器,无非就是const正向迭代器指向的节点存储的数据不能更改吗?

SO:

namespace HD
{
    //list const正向迭代器
	template <typename T>
	struct listConstIterator
	{
		typedef listNode<T>* pNode;
		typedef listConstIterator<T> self;
		pNode _pNode;

		listConstIterator<T>(pNode pNode = nullptr)
			:_pNode(pNode)
		{

		}
		const T& operator*()
		{
			return (*_pNode)._val;
		}
		self operator++(int)//后置++
		{
			self it(_pNode);
			_pNode = _pNode->_next;
			return it;
		}
		self& operator++()//前置++
		{
			_pNode = _pNode->_next;
			return *this;
		}
		self operator--(int)//后置--
		{
			self it(_pNode);
			_pNode = _pNode->_prev;
			return it;
		}
		self& operator--()//前置--
		{
			_pNode = _pNode->_prev;
			return *this;
		}
		bool operator!=(const self& it)
		{
			return _pNode != it._pNode;
		}
		bool operator==(const self& it)
		{
			return _pNode == it._pNode;
		}
		const T* operator->()
		{
			return &_pNode->_val;
		}
	};
}

仔细看,实现起来跟普通正向迭代器的区别就在于operator*和operator->这2个函数的返回值不同罢了。至于operator->这个函数到底干啥的,一会儿说的。


3.普通正向迭代器和const正向迭代器合二为一 

看到普通正向迭代器和const正向迭代器这两个类模板基本一样,那么我们完全可以写一个类模板来代替以上2个类模板:

namespace HD
{
	//list正向迭代器
	template <typename T,typename Ref,typename Ptr>
	struct listIterator
	{
		typedef listNode<T>* pNode;
		typedef listIterator<T,Ref,Ptr> self;
		pNode _pNode;

		listIterator<T,Ref,Ptr>(pNode pNode=nullptr)
			:_pNode(pNode)
		{

		}
		Ref operator*()
		{
			return (*_pNode)._val;
		}
		self operator++(int)//后置++
		{
			self it(_pNode);
			_pNode = _pNode->_next;
			return it;
		}
		self& operator++()//前置++
		{
			_pNode = _pNode->_next;
			return *this;
		}
		self operator--(int)//后置--
		{
		   self it(_pNode);
			_pNode = _pNode->_prev;
			return it;
		}
		self& operator--()//前置--
		{
			_pNode = _pNode->_prev;
			return *this;
		}
		bool operator!=(const self& it)
		{
			return _pNode != it._pNode;
		}
		bool operator==(const self& it)
		{
			return _pNode == it._pNode;
		}
		Ptr operator->()
		{
			return &_pNode->_val;
		}
	};
}

通俗易懂讲,当Ref、Ptr是T&、T*的时候,不就是普通正向迭代器吗?

当Ref、Ptr是const T&、const T*的时候,不就是const正向迭代器吗?

 1.3.list模拟实现

namespace HD
{
		//list
	template<typename T>
	class list
	{
	private:
		typedef listNode<T> node;
		typedef listNode<T>* pNode;
		typedef T value_type;
		typedef size_t size_type;
	private:
		pNode _pHead;
		size_t _size;
	public:
		typedef listIterator<T,T&,T*> i
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

X_chengonly

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

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

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

打赏作者

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

抵扣说明:

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

余额充值