STL库LIst实现

        list本质是带头双向循环链表,底层为连续空间,不容易造成内存碎片,空间利用率高,缓存利用率高,但在插入元素时,要给所有的迭代器重新赋值,因为插入元素有可能会导致重新扩容,致使原来迭代器失效,删除时,当前迭代器需要重新赋值否则会失效

  1. 迭代器:与 vector和 deque 不同,list 不支持随机访问迭代器。但它提供了双向迭代器,可以向前和向后遍历链表。
  2. 快速插入/删除:在链表的开头和结尾进行插入和删除操作的时间复杂度为 O(1)。在链表的中间进行这些操作的时间复杂度为 O(n),其中 n 是链表的大小。
  3. 内存使用:由于 list 是链表实现的,所以它的内存使用通常比 vector 或 deque 更有效,尤其是对于非常大的数据集。
  4. 容错性:如果在链表中间进行插入或删除操作时发生异常,list 可以确保链表保持一致,不会出现悬挂指针或内存泄漏

List初始化

template<class T>
	struct __list_node//__是一种命名习惯
	{
		__list_node<T>* _next;
		__list_node<T>* _prev;
		T _data;

		__list_node(const T& x = T())//构造函数初始化
			:_data(x)
			,_next(nullptr)
			,_prev(nullptr)
		{}
	};

List的运算符重载

template<class T, class Ref, class Ptr>//模板
	struct __list_iterator //迭代器
	{
		typedef __list_node<T> Node;
		typedef __list_iterator<T, Ref, Ptr> Self;
		Node* _node;

		__list_iterator(Node* node)//拿一个节点的指针就可以构造迭代器
			:_node(node)
		{}

		Ref operator*()//解引用 *it
		{
			return _node->_data;
		}

		Ptr operator->()
		{
			return &_node->_data;//取数据的地址
		}

		Self& operator++()//返回值还是迭代器 ++it
		{
			_node = _node->_next;
			return *this;
		}

		Self operator++(int)//返回值还是迭代器 it++
		{
			Self tmp(*this);
			//_node = _node->_next;
			++(*this);//效果同上
			return tmp;
		}

		Self& operator--()//--it
		{
			_node = _node->_prev;
			return *this;
		} 

		Self operator--(int)//it--
		{
			Self tmp(*this);
			//_node = _node->_prev;
			--(*this);//效果同上
			return tmp;
		}

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

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

List的迭代器

typedef __list_node<T> Node;
	public:
		typedef __list_iterator<T, T&, T*> iterator;//普通迭代器,传三个模板参数
		typedef __list_iterator<T, const T&, const T*> const_iterator;//const迭代器

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

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

		iterator begin() 
		{
			return iterator(_head->_next);//第一个有效位置
		}

		iterator end()  
		{
			return iterator(_head);//end是哨兵头节点
		}

构造函数和析构函数

        list()//带头双向循环链表
		{
			//刚开始是自己指向自己
			_head = new Node;
			_head->_next = _head;
			_head->_prev = _head;
		}


		~list()//析构函数,删除全部节点
		{
			clear();
			delete _head;
			_head = nullptr;
		}

拷贝构造和赋值

        list(const list<T>& l)//拷贝构造l2(l)
		{
			_head = new Node;
			_head->_next = _head;
			_head->_prev=_head;

			//const_iterator it = l.begin();
			//while (it != l.end())
			//{
			//	this->push_back((*it));//this->是编译器自动生成的,可不加
			//	++it;
			//}

			for (auto e : l)//效果同上
			{
				push_back(e);
			}
		}

		//list<T>& operator=(const list<T>& l)//赋值一般写法  l2=l
		//{
		//	if (this != &l)//避免自己赋值自己
		//	{
		//		clear();
		//		for (auto e : l)//遍历l3,把l3的值插入l2
		//		{
		//			push_back(e);
		//		}
		//	}
		//	return *this;
		//}

		list<T>& operator=(list<T> lt)//赋值简单写法 l2=l3,lt拷贝了l3的值,l2是this
		{
			//把l2和lt的指针互换,lt指l2原来的空间,lt出了作用域就被析构(等于把l2原来的空间给                释放了)
			swap(_head, lt._head);
			return *this;
		}

插入和删除数据

        void clear()//清除所有数据,但保留哨兵头节点
		{
			iterator it = begin();
			while(it != end())
			{
				erase(it++);
			}
		}

		void push_back(const T& x)//要用引用,因为不知道T是什么类型的
		{
			//没有节点一样可以插入
			/*Node* tail = _head->_prev;
			Node* newnode = new Node(x);

			tail->_next = newnode;
			newnode->_prev = tail;
			newnode->_next = _head;
			_head->_prev = newnode;*/

			insert(end(), x);
		}

		void insert(iterator pos, const T& x)//在pos前面插入数据
		{
			Node* cur = pos._node;//将prev newnode cur(pos)链接到一起
			Node* prev = cur->_prev;
			Node* newnode = new Node(x);

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

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

		void erase(iterator pos)
		{
			assert(pos != end());//不能删除哨兵头节点

			Node* cur=pos._node;
			Node* prev=cur->_prev;
			Node* next=cur->_next;
			delete cur;//迭代器不能被delete

			prev->_next = next;
			next->_prev = prev;
		}

		void pop_back()
		{
			//erase(iterator(_head->_prev));
			erase(--end());//效果同上,end()返回值是个迭代器
		}

		void pop_front()
		{
			erase(begin());
		}
  • 13
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值