list模拟实现

目录

前言

具体实现

节点

迭代器

list迭代器的基本内容

成员变量和typedef

构造函数

对 ++ 和 -- 运算符的重写

对 运算符* 和 运算符->的重写

对运算符== 和 运算符!=的重写

迭代器完整代码

List的具体实现

基本成员和typedef

构造函数

front 和 back

insert和erase

push_back和push_front

pop_back和push_back

empty和size

begin和end

clear和swap

析构函数

总结


前言

list底层是一个带头双向循环链表。list的重点是对其节点的封装(即迭代器的封装)。希望可以通过对list的模拟实现使各位更理解封装的意义。

具体实现

节点

节点内容很常规,一个_val存储数据,一个prev指针指向节点的前一个数据,一个next指针指向节点的后一个数据。(画图较丑,大致就是这样的图)

节点代码

	template<class T>
	struct ListNode
	{
		T _val = T();
		ListNode<T>* prev = nullptr;
		ListNode<T>* next = nullptr;

		ListNode(const T& x)
			: _val(x)
			, prev(nullptr)
			, next(nullptr)
		{}
	};

迭代器

list迭代器的基本内容

list的迭代器实质上是对 节点 即 Node 的封装,使得迭代器能实现 ++ 和 -- 等一系列迭代器所需的基本运算操作(因为list的存储空间不连续,所以Node无法直接进行迭代器所需的基本运算,因此对其进行封装)。 值得一提的是list的迭代器不是随机迭代器,不支持 + 和 - ,其主要原因是因为 + 和 - 的操作太过消耗性能了。

成员变量和typedef

由于是对 节点Node的封装,因此成员变量只有 _node。

		typedef ListIterator<T, Ref, Ptr> Self;
		typedef ListNode<T> Node;
	public:
		Node* _node = nullptr;
构造函数
		ListIterator() = default;
		ListIterator(Node* x)
		{
			_node = x;
		}
对 ++ 和 -- 运算符的重写

Self operator++(int) 是对后置++的重写, Self& operator++() 是对前置++的重写。

Self& operator++()
{
	_node = _node->next;
	return *this;
}
Self operator++(int)
{
	Self ret(_node);
	_node = _node->next;
	return ret;
}
Self& operator--()
{
	_node = _node->prev;
	return *this;
}
Self operator--(int)
{
	Self ret(_node);
	_node = _node->prev;
	return ret;
}
对 运算符* 和 运算符->的重写
Ref operator*()
{
	return _node->_val;
}
Ptr operator->()
{
	return &*this->_node;
}
对运算符== 和 运算符!=的重写
		bool operator==(const Self& x)
		{
			return _node == x._node;
		}
		bool operator!=(const Self& x)
		{
			return _node != x._node;
		}
迭代器完整代码
	template<class T , class Ref , class Ptr>
	struct ListIterator
	{
		typedef ListIterator<T, Ref, Ptr> Self;
		typedef ListNode<T> Node;
	public:
		Node* _node = nullptr;
	public:
		ListIterator() = default;
		ListIterator(Node* x)
		{
			_node = x;
		}

		Self& operator++()
		{
			_node = _node->next;
			return *this;
		}
		Self operator++(int)
		{
			Self ret(_node);
			_node = _node->next;
			return ret;
		}
		Self& operator--()
		{
			_node = _node->prev;
			return *this;
		}
		Self operator--(int)
		{
			Self ret(_node);
			_node = _node->prev;
			return ret;
		}

		Ref operator*()
		{
			return _node->_val;
		}
		Ptr operator->()
		{
			return &*this->_node;
		}


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

	};

List的具体实现

基本成员和typedef
		typedef ListNode<T> Node;
	public:
		typedef ListIterator<T, T&, T*> iterator;
		typedef ListIterator<T, const T&, const T*> const_iterator;
	private:
		Node* _head = nullptr;
构造函数
list()
{
	_head = new Node(T());
	_head->next = _head->prev = _head;
}

list(int n , const T& x = T())
{
	_head = new Node(T());
	_head->next = _head->prev = _head;
	while (n--) push_back(x);
}

template<class InputIterator>
list(InputIterator l, InputIterator r)
{
	_head = new Node(T());
	_head->next = _head->prev = _head;
	while (l != r)
	{
		push_back(*l);
		l++;
	}
}

list(initializer_list<T> il)
{
	_head = new Node(T());
	_head->next = _head->prev = _head;
	for (const auto& x : il)
	{
		push_back(x);
	}
}
front 和 back
T& front()
{
	return _head->next->_val;
}
T& back()
{
	return _head->prev->_val;
}
insert和erase

erase返回删除节点的后一个节点,避免迭代器失效问题。 insert此处也返回迭代器是为了工整,实际上list的insert不会导致迭代器失效

iterator insert(iterator pos, const T& x)
{
	Node* dest = new Node(x);
	dest->prev = pos._node->prev;
	dest->next = pos._node;
	pos._node->prev->next = dest;
	pos._node->prev = dest;
	return dest;
}
iterator erase(iterator pos)
{
	Node* dest = pos._node->next;
	dest->prev = pos._node->prev;
	pos._node->prev->next = dest;
	delete pos._node;
	return dest;
}
push_back和push_front

除下面写法外,也可以考虑对insert进行复用

		void push_back(const T& x)
		{
			Node* dest = new Node(x);
			dest->prev = _head->prev;
			dest->next = _head;
			_head->prev->next = dest;
			_head->prev = dest;
		}
		void push_front(const T& x)
		{
			Node* dest = new Node(x);
			dest->prev = _head;
			dest->next = _head->next;
			_head->next->prev = dest;
			_head->next = dest;
		}
pop_back和push_back

除下面写法外,也可以考虑对erase的复用

		void pop_front()
		{
			if (!empty())
			{
				Node* dest = _head->next;
				dest->next->prev = _head;
				_head->next = dest->next;
				delete dest;
			}
		}
		void pop_back()
		{
			if (!empty())
			{
				Node* dest = _head->prev;
				_head->prev = dest->prev;
				dest->prev->next = _head;
				delete dest;
			}
		}
empty和size
		bool empty() 
		{
			return _head->next == _head->prev;
		}
		size_t size() const
		{
			size_t n = 0;
			iterator b = _head->next;
			iterator e = _head;
			while (b != e)
			{
				n++;
				++b;
			}
			return n;
		}
begin和end
		const_iterator begin() const
		{
			return const_iterator(_head->next);
		}
		const_iterator end() const
		{
			return const_iterator(_head);
		}
		iterator begin() 
		{
			return _head->next;
		}
		iterator end()
		{
			return _head;
		}
clear和swap
void clear()
{
	iterator b = _head->next;
	iterator e = _head;
	while (b != e)
	{
		b = erase(b);
	}
}

void swap(list<T>& l)
{
	Node* m = l._head;
	l._head = _head;
	_head = m;
}
析构函数

		~list()
		{
			iterator b = _head->next, e = _head;
			while (b != e)
			{
				b = erase(b);
			}
			delete _head;
		}

总结

难点在于对迭代器的封装,同时不要忽略list类中erase迭代器通过返回值来防止因删除节点而导致的迭代器失效问题

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值