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;
	}
};
相关推荐
奔跑吧 android4 小时前
【linux kernel 常用数据结构和设计模式】【数据结构 2】【通过一个案例属性list、hlist、rbtree、xarray数据结构使用】
linux·数据结构·list·kernel·rbtree·hlist·xarray
汉克老师4 小时前
第十四届蓝桥杯青少组C++选拔赛[2023.2.12]第二部分编程题(5、机甲战士)
c++·算法·蓝桥杯·01背包·蓝桥杯c++·c++蓝桥杯
Mr_Xuhhh5 小时前
项目需求分析(2)
c++·算法·leetcode·log4j
PAK向日葵5 小时前
【C/C++】面试官:手写一个memmove,要求性能尽可能高
c语言·c++·面试
Jared_devin6 小时前
二叉树算法题—— [蓝桥杯 2019 省 AB] 完全二叉树的权值
数据结构·c++·算法·职场和发展·蓝桥杯
搞全栈小苏6 小时前
基于Qt QML和C++的MQTT测试客户端(CMakeLists实现)
xml·c++·qt
啊?啊?6 小时前
18 从对象内存到函数调用:C++ 虚函数表原理(继承覆盖 / 动态绑定)+ 多态实战
开发语言·c++·多态原理
bkspiderx6 小时前
C++标准库:文件流类
开发语言·c++
一拳一个呆瓜7 小时前
【MFC】对话框属性:X Pos(X位置),Y Pos(Y位置)
c++·mfc
一拳一个呆瓜7 小时前
【MFC】对话框属性:Center(居中)
c++·mfc