STL-list的接口使用及模拟实现

文章目录


list类的介绍
list是STL标准库提供的一个非常好用的存储容器,list的底层是一个带头双向循环链表,使我们学习STL的重点。

list类的常用接口介绍

构造相关
带参构造:
在这里插入图片描述
作用:构造的链表中包含n个val值的元素。

迭代器区间构造:
在这里插入图片描述
作用:使用迭代器区间中的元素来生成一个list对象,内容和传参的迭代器内容一样,注意传参时迭代器内的数据类型要相同。

拷贝构造:
在这里插入图片描述
作用:用一个已经存在的list对象来创建一个新的list对象,内容是相同的。

容量相关的接口
size:
在这里插入图片描述
作用:返回list对象中有效节点的个数。

empty:
在这里插入图片描述
作用:判断list对象是否为空,如果是返回true,不为空返回false。

数据访问及遍历相关的接口
front:
在这里插入图片描述
作用:返回list对象头部节点中值的引用。

back:
在这里插入图片描述
作用:返回list对象尾部节点中值的引用。

begin + end:
在这里插入图片描述
begin作用:获取list对象中第一个元素的地址
end作用:获取list对象中最后一个元素的下一个位置的地址
注意:
1、迭代器是STL中通用的遍历容器方式,迭代器是一种行为像指针一样的类型,但是迭代器的底层实现是不是指针不确定,具体看容器的底层实现方式,迭代器的使用方式也很像指针,迭代器++就是访问当前位置的下一个数据,- -(自减)就是前一个。
2、第二个const接口是提供给const对象调用的,普通的对象和const对象的迭代器是不一样的,不能混淆,因为const迭代器是不允许通过迭代器来修改数据的。

修改数据相关的接口
push_front:
在这里插入图片描述
作用:在list中第一个元素之前插入一个值为val的元素。

pop_front:
在这里插入图片描述
作用:删除list中第一个元素。

push_bcak:
在这里插入图片描述
作用:在list中尾部插入一个值为val的元素。

pop_back:
在这里插入图片描述
作用:删除list中最后一个元素。

insert:
在这里插入图片描述
作用:接口1是在迭代器对应位置之前插入一个值为val的元素,接口2是在迭代器对应位置插入n个值为val的元素,接口3是在迭代器对应位置插入某段迭代器区间内的数据。

erase:
在这里插入图片描述
作用:删除迭代器对应位置的元素,接口2是删除对应的迭代器区间内的所有元素。

claer:
在这里插入图片描述
作用:清空list中的所有有效元素。

list类的模拟实现(含各类接口)

#include<iostream>
#include<assert.h>
using namespace std;

namespace Lh
{
	template<class T>
	struct list_node               //节点
	{
		list_node(const T& x = T())//构造函数
			:_date(x)
			, _next(nullptr)
			, _prev(nullptr)
		{}

		T _date;
		list_node<T>* _next;
		list_node<T>* _prev;
	};

	template<class T, class Ref, class Ptr>       //实例化是普通对象就是普通迭代器,const对象就是const迭代器
	struct __list_iterator                        //迭代器
	{
		typedef list_node<T> Node;
		typedef __list_iterator<T, Ref, Ptr> iterator;

		Node* _node;

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

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

		// T& operator*()
		Ref operator*()          
		{
			return _node->_date;
		}
		// T* operator->()
		Ptr operator->()            //返回T*的指针 让结构体也能像指针一样去访问数据
		{
			return &(operator*());
		}
		// ++it
		iterator& operator++()
		{
			_node = _node->_next;
			return *this;
		}
		// it++
		iterator& operator++(int)
		{
			iterator tmp(*this);
			_node = _node->_next;
			return tmp;
		}
		// --it
		iterator& operator--()
		{
			_node = _node->_prev;
			return *this;
		}
		// it--
		iterator& operator--(int)
		{
			iterator tmp(*this);
			_node = _node->_prev;
			return tmp;
		}
	};

	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;             //const迭代器           

		list()         //构造函数
		{
			empty_init();
		}
		void empty_init()      //创建哨兵位头结点 并初始化
		{
			_head = new Node;
			_head->_next = _head;
			_head->_prev = _head;
		}

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

		template <class InputIterator>
		list(InputIterator first, InputIterator last)  //迭代器区间构造 
		{
			empty_init();
			while (first != last)
			{
				push_back(*first);
				++first;
			}
		}

		void swap(list<T>& x)    //交换链表结点
		{
			std::swap(_head, x._head);
		}
		//lt2(lt1)
		list(const list<T>& lt)  //拷贝构造
		{
			empty_init();
			list<T> tmp(lt.begin(), lt.end());
			swap(tmp);
		}
		list<T>& 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);   //不用++ erase返回的是下一个结点
			}
		}

		void push_back(const T& x)
		{
			//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 push_front(const T& x)
		{
			insert(begin(), x);
		}

		iterator insert(iterator pos, const T& x)
		{
			Node* cur = pos._node;
			Node* prev = pos._node->_prev;

			Node* newnode = new Node(x);

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

			return iterator(newnode);
		}

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

		iterator erase(iterator pos)
		{
			assert(pos != end());

			Node* cur = pos._node;
			Node* prev = cur->_prev;
			Node* next = cur->_next;

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

			return iterator(next);
		}
	private:
		Node* _head;
	};
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

JuLiJuLi.

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

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

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

打赏作者

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

抵扣说明:

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

余额充值