C++|list的模拟实现

C++|list的模拟实现

前言

我们模拟实现的list是带头双向循环链表,list的成员变量有指向头节点的指针。所以在实现list之前我们应该实现节点这个类型

ListNode

这个是双向链表的节点的结构

cpp 复制代码
template<class T>
	struct ListNode
	{
		
		ListNode<T>* _prev;
		ListNode<T>* _next;
		T _data;
		ListNode(const T& val = T())
			:_prev(nullptr),
			_next(nullptr),
			_data(val)
		{}
	};

list

cpp 复制代码
class list 
{
	typedef ListNode<T> Node;
	Node* _head;
public:
	list() 
	{
		_head = new Node;
		_head->_prev = _head;
		_head->_next = _head;
	}
}

list的尾插操作

cpp 复制代码
void push_back(T val =T()) 
{
	Node* tail = _head->_prev;
	Node * newnode = new ListNode(val);
	tail->_next = newnode;
	newnode->_prev = tail;
	newnode->_next = _head;
	_head->_prev = newnode;
}
	

list的尾删

cpp 复制代码
		void pop_back() 
		{
			Node* tail = _head->_prev;
			Node* pr = tail->_prev;
			_head->_prev = pr;
			pr->_next = _head;
			delete tail;
		}

因为我们想实现list的任意位置的插入的删除都要实现list的迭代器,所以我们先实现迭代器。

list的迭代器

vector中我们直接把指针当成迭代器,这是因为vector支持随机访问。但是链表的指针++ 就变成野指针了。我们想要控制这个指针的行为,就要把这个指针封装成类。类决定了行为

代码实现

cpp 复制代码
	template<class T>
	class Iterator
	{

	public:
		
		typedef ListNode<T> Node;
		typedef Iterator<T> Self;
		Node* _node;
		Iterator(Node* node)
		:_node(node)
		{}
		Self& operator++()
		{
			_node = _node->_next;
			//why
			return *this; // this 指针指向当前的iterator
			// 返回的就是iterator
		}
		Self& operator--()
		{
			_node = _node->_prev;
			return *this; 
		}
		Self operator++(int) 
		{
			Iterator tmp(*this);
			_node = _node->_next;
			return tmp; // 出了作用域tmp就被销毁了所以不能引用tmp

		}
		T& operator*()
		{
			return _node->_data;
		}
		bool operator != ( const Self &it) // 引用的是 return 回来的值 
			//因为return 回来的值本质是拷贝的一份临时变量 具有常性
		{
			return _node != it._node;
		}
		
		

	};

list的其他操作

insert

cpp 复制代码
void insert( iterator pos, T val = T()) // 缺省参数只能从右边缺省!
{
	Node *newnode = new Node(val);
	Node* cur = pos._node;
	Node* prev = cur->_prev;
	prev->_next = newnode;
	newnode->_prev = prev;

	cur->_prev = newnode;
	newnode->_next = cur;
	_size++;

}

erase

cpp 复制代码
	void erase(iterator pos) 
	{
		Node* cur = pos._node;
		Node* prev = cur->_prev;
		Node* next = cur->_next;
		prev->_next = next;
		next->_prev = prev;
		delete cur;
		_size--;
	}
cpp 复制代码
	void empty_list() 
	{
		_head = new Node;
		_head->_prev = _head;
		_head->_next = _head;
		_size = 0;
	}
	List()
	{
		empty_list();
	}
	List(const List<T> &It) 
	{
		empty_list();
		for (auto e : It) 
		{
			push_back(e);
		}
	}
	List(initializer_list<T> il)
	{
		empty_list();

		for (auto& e : il)
		{
			push_back(e);
		}
	}
	~List() 
	{
		clear();
		delete _head;
		_head = nullptr;
	}

const迭代器

cpp 复制代码
	class constlistiterator
	{
		typedef  listnode<t>  node; //内嵌类型
		typedef  constlistiterator<t> self;
	public:
		node* _node;
		constlistiterator(node* node)
			:_node(node)
		{}
	public:
		const t& operator* ()
		{
			return _node->_data;
		}
		self& operator++()
		{
			_node = _node->_next;
			return *this;
		}
		self operator++(int)
		{
			self tmp(*this);
			_node = _node->_next;
			return tmp;
		}
		self& operator--()
		{
			_node = _node->_prev;
			return *this;
		}
		self operator--(int)
		{
			/// self tmp (* this);
			self tmp(*this);
			_node = _node->_prev;
			return *tmp;
		}
		bool operator==(const self& it)
		{
			return _node == it._node;
		}
		bool operator!=(const self& it)
		{
			return _node != it._node;
		}
		 const t* operator->() 
		{
			return &_node->_data;
		}
	};
	

我们发现大部分内容都是一样的只是返回值不一样!

我们可以用模板把const迭代器和普通迭代器和成一个模板,当需要的时候编译器再现生成一个

cpp 复制代码
class ListIterator
{
	typedef  ListNode<T>  Node; //内嵌类型
	typedef  ListIterator<T,Ref,Ptr> Self;

public:
	Node* _node;
	ListIterator(Node* node)
		:_node(node)
	{}
	Ref operator* ()
	{
		return _node->_data;
	}
	Self& operator++()
	{
		_node = _node->_next;
		return *this;
	}
	Self operator++(int)
	{
		Self tmp(*this);
		_node = _node->_next;
		return tmp;
	}
	Self& operator--()
	{
		_node = _node->_prev;
		return *this;
	}
	Self operator--(int)
	{
		/// Self tmp (* this);
		Self tmp (* this);
		_node = _node->_prev;
		return *tmp;
	}
	bool operator==(const Self& it)
	{
		return _node == it._node;
	}
	bool operator!=(const Self& it)
	{
		return _node != it._node;
	}
	Ptr operator->() 
	{
		return &_node->_data;
	}
};
相关推荐
神仙别闹10 分钟前
基于MFC实现的赛车游戏
c++·游戏·mfc
小c君tt17 分钟前
MFC中 error C2440错误分析及解决方法
c++·mfc
木向1 小时前
leetcode92:反转链表||
数据结构·c++·算法·leetcode·链表
阿阿越1 小时前
算法每日练 -- 双指针篇(持续更新中)
数据结构·c++·算法
hunandede1 小时前
FFmpeg存放压缩后的音视频数据的结构体:AVPacket简介,结构体,函数
c++
hunandede2 小时前
FFmpeg 4.3 音视频-多路H265监控录放C++开发十三:将AVFrame转换成AVPacket。视频编码,AVPacket 重要函数,结构体成员学习
c++·ffmpeg·音视频
奋斗的小花生8 小时前
c++ 多态性
开发语言·c++
闲晨8 小时前
C++ 继承:代码传承的魔法棒,开启奇幻编程之旅
java·c语言·开发语言·c++·经验分享
UestcXiye9 小时前
《TCP/IP网络编程》学习笔记 | Chapter 3:地址族与数据序列
c++·计算机网络·ip·tcp
霁月风10 小时前
设计模式——适配器模式
c++·适配器模式