c++简单实现-list

       1. list是可以在常数范围内在任意位置进行插入和删除的序列式容器,并且该容器可以前后双向迭代。
       2list的底层是双向链表结构,双向链表中每个元素存储在互不相关的独立节点中,在节点中通过指针指向 其前一个元素和后一个元素。
       3. list与forward_list非常相似:最主要的不同在于forward_list是单链表,只能朝前迭代,已让其更简单高效。
       4. 与其他的序列式容器相比(array,vector,deque),list通常在任意位置进行插入、移除元素的执行效率 更好。
       5. 与其他序列式容器相比,list和forward_list最大的缺陷是不支持任意位置的随机访问,比如:要访问list 的第6个元素,必须从已知的位置(比如头部或者尾部)迭代到该位置,在这段位置上迭代需要线性的时间 开销;list还需要一些额外的空间,以保存每个节点的相关联信息(对于存储类型较小元素的大list来说这 可能是一个重要的因素)

下面是源码: 这是没有按照库里面实现的, 所以迭代器类写了两个
一个是供给可读可写的list对象, 一个是供给只读不可写的list对象

#include<iostream>

using namespace std;

//节点结构体类
template <class T>
struct ListNode
{
	T _data;
	ListNode<T>* _prev;
	ListNode<T>* _next;

	ListNode(const T& value = T())
		:_data(value)
		, _prev(nullptr)
		, _next(nullptr)
	{
	}
};


//迭代器类实现 - 可读可写
template <class T>
struct ListIterator
{
	typedef ListNode<T> Node;
	typedef ListNode<T>* pNode;
	typedef ListIterator<T> Self;

	pNode _node;

	ListIterator(pNode node)
		:_node(node)
	{}

	//解引用: 可读可写
	T& operator*()
	{
		return _node->_data;
	}

	// ptr->_year; 可以可写
	T* operator->()
	{
		return &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);
		_node = _node->_prev;
		return tmp;
	}

	//!= 
	bool operator!=(const Self& it)
	{
		return _node != it._node;
	}

	bool operator==(const Self& it)
	{
		return _node == it._node;
		//return !*this != it;
	}
};

//迭代器类实现二  - 可读不可写
template <class T>
struct ListConstIterator
{
	typedef ListNode<T> Node;
	typedef ListNode<T>* pNode;
	typedef ListConstIterator<T> Self;

	pNode _node;

	ListConstIterator(pNode node)
		:_node(node)
	{}

	//解引用: 只读
	const T& operator*()
	{
		return _node->_data;
	}
	// ptr->_year; 只读
	const T* operator->()
	{
		return &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);
		_node = _node->_prev;
		return tmp;
	}

	//!= 
	bool operator!=(const Self& it)
	{
		return _node != it._node;
	}

	bool operator==(const Self& it)
	{
		return _node == it._node;
		//return !*this != it;
	}
};

//模拟实现List类
template<class T>
class List {
public:
	typedef ListNode<T> Node;
	typedef Node* pNode;
	typedef ListIterator<T> iterator;
	typedef ListConstIterator<T> const_iterator;

	//构造函数
	List() 
		:_Head(new Node)
	{
		//首先先要自环, 很关键
		_Head->_next = _Head;
		_Head->_prev = _Head;
	}

	//迭代器构造函数
	template<class Inputiterator>
	List(Inputiterator begin, Inputiterator end) 
		:_Head(new Node)
	{
		_Head->_next = _Head;
		_Head->_prev = _Head;

		while (begin != end) {
			Pushback(*begin);
			++begin;
		}
	}


	//构造函数  --  必须要深拷贝
	List(const List<T>& lst)
		:_Head(new Node)
	{
		_Head->_next = _Head;
		_Head->_prev = _Head;

		for (auto it : lst) {
			Pushback(it);		//Insert也可以
		}

	}

	//赋值运算符重载 - 现在写法
	List<T>& operator=(List<T>& lst) {
		swap(_Head, lst._Head);
		return *this;
	}
	
	//析构函数
	~List() {
		Clear();
		if (_Head) {
			delete _Head;
			_Head = nullptr;
		}
	}

	//尾插元素
	void Pushback(const T& val) {
		pNode prev_Node = _Head->_prev;		//得到尾节点
		pNode newNode = new Node(val);

		prev_Node->_next = newNode;
		newNode->_prev = prev_Node;
		newNode->_next = _Head;
		_Head->_prev = newNode;
		//下面是两种不同的写法, 代码复用
		//Insert(iterator(_Head), val);
		//INsert(end(), val);
	}

	//头插元素
	void PushFront(const T& val) {
		pNode next_Node = _Head->_next;
		pNode newNode = new Node(val);

		_Head->_next = newNode;
		newNode->_prev = _Head;
		newNode->_next = next_Node;
		next_Node->_prev = newNode;
		//Insert(iterator(_Head->_next), val);
		//Insert(begin(), val);
	}

	//头删
	void PopFront() {
		//方法实现和头插一样, 不重点写
		Erase(begin());
	}
	
	//尾删
	void Popback() {
		Erase(--end());
	}

	//任意位置插入 - 传入的迭代器和值
	void Insert(iterator pos, const T& val) {
		//在迭代器的位置插入  --  迭代器是一个类
		pNode node = pos._node;

		//先得到Node前面的节点
		pNode prev = node->_prev;

		pNode newNode = new Node(val);
		prev->_next = newNode;
		newNode->_prev = prev;
		newNode->_next = node;
		node->_prev = newNode;

	}

	//任意位置删除
	iterator Erase(iterator pos) {
		//在这块头节点_Head是不能删除的
		if (pos._node != _Head) {
			pNode node = pos._node;
			pNode prev = node->_prev;
			prev->_next = node->_next;
			node->_next->_prev = prev;
			++pos;
		}

		return pos;
	}
	
	//判空函数
	bool Empty() {
		if (_Head->_next == _Head)
			return true;
		else
			return false;
	}

	//清理函数
	void Clear() {
		if (!Empty()) {
			pNode cur = _Head->_next;
			while (cur != _Head) {
				pNode next = cur->_next;
				delete cur;
				cur = next;
			}

			//因此_Head不是在堆上开辟的, 因此不需要释放, 但是自环操作一定要有, 作为一些为空等一些接口的判断依据。
			_Head->_next = _Head;
			_Head->_prev = _Head;
		}

		//写法2
		//if (!Empty()) {
		//	iterator it = begin();
		//	while (it != end()) {
		//		Erase(it);
		//	}
		//}
	}
	
	//容器大小or长度
	size_t Size() {
		size_t count = 0;
		pNode tmp = _Head->_next;
		while(tmp != _Head)
		{
			++count;
			tmp = tmp->_next;
		}
		return count;
	}
	
	//下面是迭代器接口
	iterator begin() {
		return iterator(_Head->_next);
	}

	iterator end() {
		return iterator(_Head);
	}

	const_iterator begin() const {
		return const_iterator(_Head->_next);
	}

	const_iterator end() const {
		return const_iterator(_Head);
	}


private:
	pNode _Head;
};

下面是借鉴库里面实现list容器方法写的 - 就是在迭代器类模板进行修改。
我们知道const 实例化的list对象和 非const 实例化list对象关键就在于修改权限,
非const实例化的list对象在使用迭代器时是需要迭代器提供可读可写的, const修饰则不相同, 因此const修饰的无法调动正常的迭代器, 因此权限可以缩小但是不能放大, 所以会多写一个特殊的可读不可写的迭代器类, 库里面实现的方法巧妙地解决了这个问题, 使得了一个迭代器类就可以搞定 - 下面代码请欣赏!

关于迭代器问题, 也是在这块体现出来, 为什么vector, string可以不写迭代器类就可以完成迭代器的功能, 但是list不行呢? 需要手动实现, 这是一个值得思考总结的问题。

#include<iostream>

using namespace std;

template <class T>
struct ListNode
{
	T _data;
	ListNode<T>* _prev;
	ListNode<T>* _next;

	ListNode(const T& value = T())
		:_data(value)
		, _prev(nullptr)
		, _next(nullptr)
	{
	}
};

/*区别一*/
//迭代器实现 - 既可以做到可读可写, 又可以做到可读不可写!
template <class T, class Ref, class Ptr>
struct ListIterator
{
	typedef ListNode<T> Node;
	typedef ListNode<T>* pNode;
	typedef ListIterator<T, Ref, Ptr> Self;

	pNode _node;

	ListIterator(pNode node)
		:_node(node)
	{}

	//解引用: 可读可写
	Ref operator*()
	{
		return _node->_data;
	}
	// ptr->_year; 可以可写
	Ptr operator->()
	{
		return &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);
		_node = _node->_prev;
		return tmp;
	}

	//!= 
	bool operator!=(const Self& it)
	{
		return _node != it._node;
	}

	bool operator==(const Self& it)
	{
		return _node == it._node;
		//return !*this != it;
	}
};


template<class T>
class List {
public:
	typedef ListNode<T> Node;
	typedef Node* pNode;
	
	/*区别2*/
	typedef ListIterator<T, T&, T*> iterator;
	typedef ListIterator<T, const T&, const T*> const_iterator;

	List() 
		:_Head(new Node)
	{
		//首先先要自环, 很关键
		_Head->_next = _Head;
		_Head->_prev = _Head;
	}

	//迭代器构造函数
	template<class Inputiterator>
	List(Inputiterator begin, Inputiterator end) 
		:_Head(new Node)
	{
		_Head->_next = _Head;
		_Head->_prev = _Head;

		while (begin != end) {
			Pushback(*begin);
			++begin;
		}
	}


	//构造函数  --  必须要深拷贝
	List(const List<T>& lst)
		:_Head(new Node)
	{
		_Head->_next = _Head;
		_Head->_prev = _Head;

		for (auto it : lst) {
			Pushback(it);		//Insert也可以
		}

	}

	//赋值运算符重载 - 现在写法
	List<T>& operator=(List<T>& lst) {
		swap(_Head, lst._Head);
		return *this;
	}

	~List() {
		Clear();
		if (_Head) {
			delete _Head;
			_Head = nullptr;
		}
	}

	//尾插元素
	void Pushback(const T& val) {
		pNode prev_Node = _Head->_prev;		//得到尾节点
		pNode newNode = new Node(val);

		prev_Node->_next = newNode;
		newNode->_prev = prev_Node;
		newNode->_next = _Head;
		_Head->_prev = newNode;
		//Insert(iterator(_Head), val);
		//INsert(end(), val);
	}

	//头插元素
	void PushFront(const T& val) {
		pNode next_Node = _Head->_next;
		pNode newNode = new Node(val);

		_Head->_next = newNode;
		newNode->_prev = _Head;
		newNode->_next = next_Node;
		next_Node->_prev = newNode;
		//Insert(iterator(_Head->_next), val);
		//Insert(begin(), val);
	}

	//头删
	void PopFront() {
		//方法实现和头插一样, 不重点写
		Erase(begin());
	}

	void Popback() {
		Erase(--end());
	}

	//任意位置插入
	void Insert(iterator pos, const T& val) {
		//在迭代器的位置插入  --  迭代器是一个类
		pNode node = pos._node;

		//先得到Node前面的节点
		pNode prev = node->_prev;

		pNode newNode = new Node(val);
		prev->_next = newNode;
		newNode->_prev = prev;
		newNode->_next = node;
		node->_prev = newNode;

	}

	//删除任意迭代器位置的
	iterator Erase(iterator pos) {
		//在这块头节点_Head是不能删除的
		if (pos._node != _Head) {
			pNode node = pos._node;
			pNode prev = node->_prev;
			prev->_next = node->_next;
			node->_next->_prev = prev;
			++pos;
		}

		return pos;
	}

	bool Empty() {
		if (_Head->_next == _Head)
			return true;
		else
			return false;
	}


	void Clear() {
		//清理函数
		if (!Empty()) {
			pNode cur = _Head->_next;
			while (cur != _Head) {
				pNode next = cur->_next;
				delete cur;
				cur = next;
			}

			//因此_Head不是在堆上开辟的, 因此不需要释放, 但是自环操作一定要有, 作为一些为空等一些接口的判断依据。
			_Head->_next = _Head;
			_Head->_prev = _Head;
		}

		//写法2
		//if (!Empty()) {
		//	iterator it = begin();
		//	while (it != end()) {
		//		Erase(it);
		//	}
		//}
	}

	size_t Size() {
		size_t count = 0;
		pNode tmp = _Head->_next;
		while(tmp != _Head)
		{
			++count;
			tmp = tmp->_next;
		}
		return count;
	}

	iterator begin() {
		return iterator(_Head->_next);
	}

	iterator end() {
		return iterator(_Head);
	}

	const_iterator begin() const {
		return const_iterator(_Head->_next);
	}

	const_iterator end() const {
		return const_iterator(_Head);
	}


private:
	pNode _Head;
};
 

能力有限, 很多接口考虑不到, 请多多包涵! - 祝各位新年快乐!

发布了25 篇原创文章 · 获赞 16 · 访问量 922

猜你喜欢

转载自blog.csdn.net/weixin_44024891/article/details/104149673