list模拟实现

目录

list 介绍

list 结构: 

迭代器

迭代器失效问题

 list代码实现


list 介绍
1. list是可以在常数范围内在任意位置进行插入和删除的序列式容器,并且该容器可以前后双向迭代。
2. list的底层是双向链表结构,双向链表中每个元素存储在互不相关的独立节点中,在节点中通过指针指向其前一个元素和后一个元素。
3. listforward_list非常相似:最主要的不同在于forward_list是单链表,只能朝前迭代,已让其更简单高效。
4. 与其他的序列式容器相比(arrayvectordeque)list通常在任意位置进行插入、移除元素的执行效率更好。
5. 与其他序列式容器相比,listforward_list最大的缺陷是不支持任意位置的随机访问.
list 结构: 

节点定义

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

	list_node(const T& x = T())
		:_data(x)
		, _next(nullptr)
		, _prev(nullptr)
	{}
};

 链表定义:

template<class T>
class list
{
	typedef list_node<T> Node;
public:
private:
	Node* _head;
	size_t _size;
};
迭代器

迭代器封装了底层的实现,不暴露底层的实现细节,又提供统一的访问方式,这使得容器都可以用相似的方法来访问。对于vector和string而言,物理空间是连续的,通过对指针的++或者--,我们就可以访问当前位置的前一个位置或者后一个位置。

但是对于list而言,它的物理空间不是连续的,我们无法直接通过++或者--来直接访问当前位置的前一个位置或者后一个位置,所以通过对指针++或者--不能实现list的迭代器,因此,我们需要进行一些特殊处理,那么怎么处理呢?

我们可以通过对运算符进行重载来帮助我们来找到当前结点的前一个位置或者下一个位置。

template<class T, class Ref, class Ptr>

//说明
//T:链表中节点的数据类型。
//Ref:通常用于指定迭代器的引用类型(比如T&表示非常量引用, const T&表示常量引用)。 
//但在给出的代码中,这个类型并没有直接用于定义迭代器的成员或方法。
//Ptr :通常用于指定迭代器的指针类型(比如T*表示非常量指针,constT*表示常量指针)。
//同样,在给出的代码中,这个类型也没有被直接使用。

struct __list_iterator
{
	typedef list_node<T> Node;
	typedef __list_iterator<T, Ref, Ptr> self;
	Node* _node;

	__list_iterator(Node* node)
		:_node(node)
	{}

	self& operator++()
	{
		_node = _node->_next;
		return *this;
	}

	self& operator--()
	{
		_node = _node->_prev;
		return *this;
	}

	self operator++(int)
	{
		self tmp(*this);
		_node = _node->_next;

		return tmp;
	}

	self operator--(int)
	{
		self tmp(*this);
		_node = _node->_prev;

		return tmp;
	}

	Ref operator*()
	{
		return _node->_data;
	}

	Ptr operator->()
	{
		return &_node->_data;
	}

	bool operator!=(const self& s)
	{
		return _node != s._node;
	}

	bool operator==(const self& s)
	{
		return _node == s._node;
	}
};
迭代器失效问题

有关迭代器失效问题:list是一个双向链表,基于这个结构特性,迭代器失效情况与vector不同

插入元素:在list中任意位置插入元素不会导致迭代器失效,除非迭代器正好指向被插入的元素,这是因为链表中的插入操作只需要修改几个指针,而不需要移动其它元素。

删除元素:从list中删除元素只会导致指向被删除元素的迭代器失效,其它迭代器仍然有效,因为链表中的删除操作不会移动其他元素。

重新分配:与vector不同,list的迭代器不会因为重新分配内存而失效,因为list不需要连续的内存块。

解决办法同vector解决迭代器失效一样,针对插入元素,返回新插入元素的迭代器

针对删除元素,返回被删除元素的下一个元素的迭代器

 list代码实现
template<class T>
class list
{
	typedef list_node<T> Node;
public:
	typedef __list_iterator<T, T&, T*> iterator;
	typedef __list_iterator<T, const T&, const T*> const_iterator;

	//typedef __list_const_iterator<T> const_iterator;

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

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

	iterator begin()
	{
		//return iterator(_head->_next);
		return _head->_next;
	}

	iterator end()
	{
		//return iterator(_head->_next);
		return _head;
	}

	void empty_init()
	{
		_head = new Node;
		_head->_next = _head;
		_head->_prev = _head;

		_size = 0;
	}

	list()
	{
		empty_init();
	}

	list(const list<T>& lt)
	{
		empty_init();
		for (auto e : lt)
		{
			push_back(e);
		}
	}

	// lt3 = lt1
	/*list<int>& operator=(const list<int>& lt)
	{
		if (this != &lt)
		{
			clear();
			for (auto e : lt)
			{
				push_back(e);
			}
		}

		return *this;
	}*/

	void swap(list<T>& lt)
	{
		std::swap(_head, lt._head);
		std::swap(_size, lt._size);
	}

	list<int>& operator=(list<int> lt)
	{
		swap(lt);
		return *this;
	}

	~list()
	{
		clear();

		delete _head;
		_head = nullptr;
	}

	void clear()
	{
		iterator it = begin();
		while (it != end())
		{
			it = erase(it);
		}
	}

	void push_back(const T& x)
	{
		insert(end(), x);
	}

	void push_front(const T& x)
	{
		insert(begin(), x);
	}

	void pop_front()
	{
		erase(begin());
	}

	void pop_back()
	{
		erase(--end());
	}

	iterator insert(iterator pos, const T& x)
	{
		Node* cur = pos._node;
		Node* newnode = new Node(x);

		Node* prev = cur->_prev;

		prev->_next = newnode;
		newnode->_prev = prev;

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

		++_size;

		return iterator(newnode);
	}

	iterator erase(iterator pos)
	{
		Node* cur = pos._node;
		Node* prev = cur->_prev;
		Node* next = cur->_next;

		delete cur;
		prev->_next = next;
		next->_prev = prev;

		--_size;

		return iterator(next);
	}

	size_t size()
	{
		return _size;
	}

private:
	Node* _head;
	size_t _size;
};
  • 118
    点赞
  • 42
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 82
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 82
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

新绿MEHO

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

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

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

打赏作者

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

抵扣说明:

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

余额充值