STL-List

前言

我们将进入到C++STL 的学习。STL在各各C++的头文件中,以源代码的形式出现,不仅要会用,还要了解底层的实现。源码之前,了无秘密。
STL六大组件

image-20240323151905853

Container通过Allocator取得数据储存空间,Algorithm通过Iterator存取Container内容,Functor可以协助Algorithm完成不同的策略变化,Adapter可以修饰或者套接Functor。

序列式容器sequential containers

List

image-20240407105110184

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

List constructor

list()构造空的list
list (size_type n, const value_type& val = value_type())构造的list中包含n个值为val的元素
list (const list& x)拷贝构造函数
list (InputIterator first, InputIterator last)用[first, last)区间中的元素构造list

List modify

empty检测list是否为空,是返回true,否则返回false
size返回list中有效节点的个数
front/back返回list的第一个节点/最后一个节点中值的引用
push_front/pop_front在list首元素前插入值为val的元素/删除第一个元素
push_back/pop_back在list尾部插入值为val的元素/删除最后一个元素
insert在pos位置中插入值为val的元素
erase删除pos位置的元素
swap交换两个list中的元素
clear清空list中的有效元素

模拟实现List

迭代器部分,这个是重点,不再是普通的原生指针,而是对指针的封装。

template<class T, class Ref, class Ptr>
	struct __list_iterator
	{
		typedef ListNode<T> Node;
		//每新增一个模板参数,只需要加到self就行了
		typedef __list_iterator<T, Ref, Ptr> self;

		typedef Ptr pointer; //内嵌类型

		Node* _node;

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

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

		//++it
		self& operator++()
		{
			_node = _node->_next;
			return *this;
		}
		//it++
		self operator++(int)
		{
			self tmp(*this);
			_node = _node->_next;
			return tmp;
		}
		//--it
		self& operator--()
		{
			_node = _node->_prev;
			return *this;
		}
		//it--
		self operator--(int)
		{
			self tmp(*this);
			_node = _node->_prev;
			return tmp;
		}

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

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

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

	};

反向迭代器

namespace jt
{
	/*template<class Iterator>*/

	//我们使用三个模板参数
	template<class Iterator, class Ref, class Ptr>
	class reverse_iterator
	{
		typedef reverse_iterator<Iterator, Ref, Ptr> self;
		reverse_iterator(Iterator it)
			:_it(it)
		{} 

		//rbegin() == end()  begin() == rend()
		self operator*()const
		{
			Iterator prev = _it;
			return *--prev; //返回前一个值
		}

		//取__list_iterator 中的 typedef Ptr pointer;
		//假如是vercor的话iterator中是没有typedef Ptr pointer;
		//因为vector的iterator没有封装,只是原生指针,就不能用了。
		//STL中用迭代器萃取来实现的。

		//加typename 举个例子 
		//vector<int> v 能过
		//vector<T> v 不能过
		//typename vector<T> v 能过
		//typename Iterator::pointer operator*()const
		//{
		//	Iterator prev = _it;
		//	return *--prev; //返回前一个值
		//}

		Ref& operator++()
		{
			--_it;
			return *this;
		}

		Ptr operator->()
		{
			return &operator*();
		}

		self& operator--()
		{ 
			++_it;
			return *this;
		}

		bool operator==(const self& rit) const
		{
			return _it != rit._it;
		}

	private:
		Iterator _it;
	};
}

list主体

template<class T>
	struct ListNode
	{
		ListNode<T>* _next;
		ListNode<T>* _prev;
		T _data;
		ListNode(const T& data = T())
			:_next(nullptr)
			, _prev(nullptr)
			, _data(data)
		{}
	};
template <class T>
	class list
	{
		typedef ListNode<T> Node;
		
	public:
		typedef __list_iterator<T, T&, T*> iterator;
		typedef __list_iterator<T, const T&, const T*> const_iterator;

		typedef reverse_iterator<T, T&, T*> iterator;
		typedef reverse_iterator<T, const T&, const T*> const_iterator;

		reverse_iterator rbegin()
		{
			return reverse_iterator(end());
		}

		reverse_iterator rend()
		{
			return reverse_iterator(begin());
		}

		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);
		}

	public:
		void push_back(const T& x)
		{
			/*Node* new_node = new Node(x);
			Node* tail = _head->_prev;
			tail->_next = new_node;
			new_node->_prev = tail;
			_head->_prev = new_node;
			new_node->_next = _head;*/
			insert(end(), x);
		}

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

		void pop_back()
		{
			erase(--end()); //调用迭代器的--
		}

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

		void clear()
		{
			iterator it = begin();
			while (it != end())
			{
				//iterator del = it++; //后置++保留了第一个哨兵位头结点
				//delete del._node;
				earse(it++);

			}
			/*_head->_next = _head;
			_head->_prev = _head;*/
		}

		//不存在迭代器失效问题
		iterator insert(iterator pos, const T& x)
		{
			Node* cur = pos._node;
			Node* prev = cur->_prev;
			Node* new_node = new Node(x);

			prev->_next = new_node;
			new_node->_prev = prev;
			new_node->_next = cur;
			cur->_prev = new_node;
			return iterator(new_node);
		}

		//存在迭代器失效,pos指向的空间给delete了
		iterator earse(iterator pos)
		{
			assert(pos != end());
			Node* prev = pos._node->_prev;
			Node* next = pos._node->_next;
			delete pos._node;
			prev->_next = next;
			next->_prev = prev;
			return iterator(next);
		}

	public:
		list()
		{
			_head = new Node();
			_head->_next = _head;
			_head->_prev = _head; 
		}

	/*	list(const list<T>& l)
		{
			_head = new Node();
			_head->_next = _head;
			_head->_prev = _head;
			for (auto x : l) push_back(x);
		}*/

	/*	list<T>& operator=(const list<T>& l)
		{
			if (this != &l) clear();

			for (auto x : l) push_back(x);
			return *this;
		}
*/
		template<class InputIterator>
		list(InputIterator first, InputIterator last)
		{
			_head = new Node();
			_head->_next = _head;
			_head->_prev = _head;
			while (first != last)
			{
				push_back(*first);
				++first;
			}
		}

		list(const list<T>& l)
		{
			_head = new Node();
			_head->_next = _head;
			_head->_prev = _head;
			list<T> tmp(l.begin(), l.end());
			std::swap(_head, tmp._head);
		}

		//调用list<int> l (100, 1)
		//会和list(InputIterator first, InputIterator last)冲突
		list(size_t n, const T& val = T())
		{
			_head = new Node();
			_head->_next = _head;
			_head->_prev = _head;
			for (size_t i = 0; i < n; i++)
				push_back(val);
		}

		//重载一个int版本
		list(int n, const T& val = T())
		{
			_head = new Node();
			_head->_next = _head;
			_head->_prev = _head;
			for (size_t i = 0; i < n; i++)
				push_back(val);

		}

		list<T>& operator=(list<T>& l)
		{
			swap(_head, l._head);
			return *this;
		}
		
		~list()
		{	 
			clear();
			delete _head;
			_head = nullptr;
		}
	private:
		Node* _head;

	};
  • 6
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值