list模拟实现

list原理讲解

在C++中SGI版本的STL中的list容器是用带头双向循环链表来实现的;
那么什么是带头双向循环链表?
如下图:
在这里插入图片描述
该链表有一个head头节点,该节点不存储任何有效数据!仅用于链接第一个有效节点和最后一个有效节点;head的前一个节点就是该链表的最后一个有效节点,head的后一个节点,就是该链表的第一个有效节点!
只要我们能够找到head节点,我们就能找到整条带头双向循环链表!
使用该结构存储数据的话,插入和删除数据都非常的快,时间复杂度为O(1)
相比于前面的vector来说vector的插入和删除数据效率都比较低!当我们需要进行大量的插入和删除数据的时候我们可以考虑使用list数据结构!

节点结构

该节点,有数据域和指针域,其中数据域专门用来存储数据,指针域细分的话,又有两个指针域:前指针域(用于存储前一个节点的指针)、后指针域(用于存储后一个节点的指针);
因此我们可以这样设置节点数据结构:

//节点
	template <class T>
	struct list_node
	{
		T _date;
		list_node<T>* _prev;
		list_node<T>* _next;
		list_node(const T& val = T())//这里可以考虑使用缺省参数;//由于模板的出现,这就要求了对于内置类型必须提供构造函数,不然的话对于这种情况const T& val = T()我们无法处理,因为我们不知道T的具体类型是什么,无法准确的给缺省值!同时const引用可以延长匿名对象的生命周期,直到引用所在作用域销毁
			:_date(val), _prev(nullptr), _next(nullptr) {}
	};

我们可以用一个模板来写一个节点数据结构,因为节点的数据域可以存储任何类型的数据,同时我们可以为该节点提供一个构造函数,方便后续向节点插入数据的需求!
同时这里我们用了struct来创建节点类,不用class,是因为struct创建的类的默认权限是public更为方便我们后续的操作,class创建的类的默认权限是private的,当我们将类内部的成员全部放开时,我们可以利用struct来创建类!当然也可以用class,只不过这时候我们需要加上public访问限定符!

list类设计

list类也应该成一个模板类,因为list可以插入任何类型的元素!

template <class T>
{
public:
private:
//list的成员我们可以设计为一个list_node<T>*的指针
//该指针用于存储带头双向循环链表的head节点;
//只要我们找到了head节点,我们就能找到整条链表!
//list_node<T> * _head;//当然这里我们可以考虑typedef一下list_node<T>,毕竟这个类型太长了,写起来比较麻烦,当然我们也可以不typedef,直接使用原生类型
typedef list_node<T> node;
node*_head;
}

既然list类成员已经设计出来了,那么我们现在就创建一个带头双向循环链表来玩一玩;
首先要有一个带头双向循环链表,我们就得现有一个head节点,方便我们list对于整条链表的管理;
因此我们的构造函数可以写成:

list()
{
_head=new node;//创建一个头节点
_head->_prev=_head->_next=_head;//让其头节点的_next指针和_prev指针都指向自己,因为现在一个元素也没有,_head的下一个节点就是自己,_head的前一个节点也是自己
}

在这里插入图片描述

push_back

在上面,我们已经实现出list的一个简单无参构造函数,我们现在就有了_head节点,我们现在就只需要插入元素了,对于插入元素来说很简单:
在这里插入图片描述

要实现尾插,就需要找到最后一个一个节点,那么最后一个节点在哪里?
_head->_prev不就是最后一个节点嘛,最后在将new_node节点的_next域链接向_head节点,_head的_prev域链接向new_node节点就可以了;
在这里插入图片描述

void push_back(const T&val)
{
	node*new_node=new node(val);
	node*tail=_head->_prev;//尾节点
	tail->_next=new_node;
	new_node->_prev=tail;
	new_node->_next=_head;
	_head->_prev=new_node;
}

Iterators:

现在我们已经可以向list里面插入元素了,但是我们想打印一下list元素,以此来检查一下我们push_back的正确性!
为此我们就要遍历整个链表,遍历的话我们就需要迭代器,可是现在有个问题,我们应该拿什么作为迭代器呢?
原生的节点指针(list_node<T>*)吗?
在这里插入图片描述
如果是这样的话,那么迭代器该如何往后迭代呢?要知道迭代器只允许使用++、–等迭代方式,是不允许->这样的迭代方式的,但是我们使用++、–等方式对我们的迭代器进行迭代的话,我们能保证it++就是下一个节点的指针吗?这显然是无法保证的,因为节点与节点之间都是不连续的,it++自然也就无法保证++过后就一定是下一个节点的指针!但凡list的结构是类似于vector、string的连续空间我们都可以使用原生指针来充当迭代器!但对于list不行,因此list中使用原生指针作为迭代器的想法被直接pass掉!
那么有没有什么既可以指向对应节点,同时又能使用++、–来进行迭代的东西呢?

当然有,我们可以对原生指针进行封装!封装成一个类,让这个类充当迭代器,然后在这个类内部重载++、–等运算符,以此来实现迭代器的迭代;

事不宜迟,咱们现在就来干一个:

template <class T//元素类型>
struct _list_iterator
{			//用于初始化迭代器
		_list_iterator(list_node<T>* node=nullptr)
		:_node(node)
		{}
		//由于_list_iterator<T> 这个迭代器类型使用起来比较麻烦,有需要大量的使用,我们这里解直接typedef一下;
		typedef _list_iterator<T> self;//self就表示迭代器的类型,本质还是_list_iterator<T>
		
		//开始重载++、--、*、!=等运算符
		self&operator++()//前置++
		{
			assert(_node);//防止_node为nullptr,避免出现这种情况:_list_iterator it;//此时it会调用无参构造,_node会被初始化成nullptr,这时候如果再使用++it就会对nullptr解引用,会崩溃
			_node=_node->_next;
			return *this;
		}
		
		self operator++(int)//后置++
		{
		assert(_node);
		self tmp(*this);//这里可以使用默认拷贝构造,因为在迭代器类中不会对节点进行析构
		++(*this);
		return tmp;
		}
		
		T& operator*()//对迭代器解引用,返回数据域的值
		{
		assert(_node);
		return _node->_date;
		}
		
		bool operator!=(const self&it)//两个迭代器之间进行比较
		{
		//这也是迭代器继续迭代比较运算符
		//对于list这类迭代器,就不在适合使用>、<等运算符进行比较了,因为节点不是连续的
		return _node!=it._node;
		}
		
		self&operator--()//前置--
		{
			assert(_node);
			_node=_node->_prev;
			return *this;
		}
		
		self operator++(int)//后置--
		{
		assert(_node);
		self tmp(*this);//这里可以使用默认拷贝构造,因为在迭代器类中不会对节点进行析构
		--(*this);
		return tmp;
		}
		//成员变量
	list_node<T> *_node;//用于存储当前迭代器所迭代的位置	
}

实现了迭代器,我们就可以在list类内部使用了,不过我们需要先将我们实现的迭代器的名字在list类内部typedef一下,因为STL的所有容器的迭代器都是iterator,这算是一种默认的规范!
在list内部加上:

typedef _list_iterator<T> iterator;

begin与end

有了迭代器在list内部的begin与end函数就可以写了
在这里插入图片描述

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

const对象的迭代器

我们上面实现的迭代器,还是有缺陷的,比如上面的begin与end我们只是实现了普通list对象,对于const对象也无法调用begin、end,换而言之const不能使用迭代器进行迭代,只有普通list对象可以;
那么有读者就说,const对象调不了,begin、end是因为begin、end的this指针权限过大,我们在重载一个const对象的begin、end不就好了:

iterator begin()const
{
return iterator(_head->_next);
}
iteratro end()const
{
return iterator(_head);
}

嗯,这样的话const对象确实能够进行迭代了,可是新问题又来了,(*迭代器)的时候,也能改变迭代器所指节点的值!因为operator*()的返回值是T&,嗯???这似乎与我们的预期相违背了,const对象的值怎么能通过迭代去修改呢?我们必须解决这个问题;
我们可以不可在普通迭代器前面加个const来充当const对象的迭代器呢?
比如:

typedef _list_iteratro iterator;
//iterator不是普通对象的迭代器嘛
//那么const对象的迭代器可不可以是:
typedef const _list_iteratro const_iterator;
//const _list_iteratro 来充当const对象的迭代器?
//答:不可以!!!如果我们这样做了的话,我们迭代器本身就无法完成迭代了!
//迭代器本身都无法完成迭代,那还叫个屁的迭代器!
//这就好比,int a=10;与const int b=10;
//a可以实现++、--,但是b就不可以!

怎么解决呢?
1、重新为const对象协议一个迭代器,其中operator*()的返回值设置为const T &;
2、按照方法1确实可以解决问题,可是太麻烦了,你看嘛我们const迭代器与普通对象的迭代器都需要实现++、–等迭代操作,但是这两个迭代器的唯一区别就是operator*()的返回值,const迭代器是const T& ,而普通迭代器是T& 二者之间就差一个const,要是我们能用一个“变量”来控制operator*的返回值就好了!
那么能不能实现呢?
当然可以,我们可以在_list_iterator模板参数列表,再添加一个参数Ref,以此来控制operator*()的返回值,但我们给_list_iterator类模板传入不同的参数时,_list_iterator类模板就会给我们实例化出不同的具体类型!
因此我们的迭代器可以优化成:

template <class T,class Ref>
struct _list_iterator
{			//用于初始化迭代器
		_list_iterator(list_node<T>* node=nullptr)
		:_node(node)
		{}
		//由于_list_iterator<T> 这个迭代器类型使用起来比较麻烦,有需要大量的使用,我们这里解直接typedef一下;
		typedef _list_iterator<T,Ref> self;//self就表示迭代器的类型,本质还是_list_iterator<T,Ref>
		
		//开始重载++、--、*、!=等运算符
		self&operator++()//前置++
		{
			assert(_node);//防止_node为nullptr,避免出现这种情况:_list_iterator it;//此时it会调用无参构造,_node会被初始化成nullptr,这时候如果再使用++it就会对nullptr解引用,会崩溃
			_node=_node->_next;
			return *this;
		}
		
		self operator++(int)//后置++
		{
		assert(_node);
		self tmp(*this);//这里可以使用默认拷贝构造,因为在迭代器类中不会对节点进行析构
		++(*this);
		return tmp;
		}
		
	Ref operator*()//对迭代器解引用,返回数据域的值,根据Ref的不同,来决定operator\*()的返回值类型
		{
		assert(_node);
		return _node->_date;
		}
		
		bool operator!=(const self&it)//两个迭代器之间进行比较
		{
		//这也是迭代器继续迭代比较运算符
		//对于list这类迭代器,就不在适合使用>、<等运算符进行比较了,因为节点不是连续的
		return _node!=it._node;
		}
		
		self&operator--()//前置--
		{
			assert(_node);
			_node=_node->_prev;
			return *this;
		}
		
		self operator++(int)//后置--
		{
		assert(_node);
		self tmp(*this);//这里可以使用默认拷贝构造,因为在迭代器类中不会对节点进行析构
		--(*this);
		return tmp;
		}
		//成员变量
	list_node<T> *_node;//用于存储当前迭代器所迭代的位置	
}

这样的话,再list内部我们就需要重新实例化一下普通对象与const对象的迭代器了:

typedef _list_iterator<T,T&> iterator;//普通list对象的迭代器
typedef _list_iterator<T,const T&> const_iterator;//const对象的迭代器
//由于传递的模板参数不同,_list_iterator<class T,class Ref>会实例化出两份不同类型的迭代器!

重载->运算符

对于list迭代器来说,我们可以说是模拟原生指针的行为,比如(*迭代器)返回的就是节点数据域的值!
那么如果现在有一个结构体:

struct AA
{
int _a;
int _b;
   AA(int a=0;int b=0):
   _a(a),_b(b){}
}
int main()
{
 list<int> l1;
 l1.push_back(AA(1,2));
 list<int> :: iterator it=l1.begin();
 //正常写法:
 //std::cout<<(*it)._a<<" "<<(*it)._b<<std::endl;
 //可是现在我们嫌弃上面那种方法比较麻烦,我们可不可以直接使用下面这种方法来实现呢?
 std::cout<<it->_a<<" "<<it->_b<<std::endl;
 //答案是可以的,因此在迭代器内部,我们需要重载->运算符;
}

迭代器内部重载->运算符

T*operator->()
{
return &_node->date;
}

我们只有实现了上诉部分的运算符重载,我们才能直接使用:

 std::cout<<it->_a<<" "<<it->_b<<std::endl;

语句;
可是我们仔细观察一下operator->的返回值就会发现很奇怪的地方,operator->的返回值是T*,那么正确访问_a成员的方式,不应该是:it->->_a 不应该是两个箭头吗?为什么这里只需要一个->就可以!这里的话就与重载->的特殊性有关了,建议观看大佬的这篇文章:C++箭头(->)重载函数这位大佬讲的很明白!
现在又有个问题,如果const对象的迭代使用operator->()函数的或是不是也会改变节点数据域的值?
因为operator->的返回值是T*,没有const限制!为此为了限制这一“漏洞”,我们可以效仿operator*()返回值的作法,在增加一个模板参数,那么_list_iterator就会被优化成:

template<class T,class Ref,class Ptr>
struct _list_iterator
	{
		_list_iterator(list_node<T>* node = nullptr)
			:_node(node) {}

		typedef _list_iterator<T, Ref, Ptr > self;
		self& operator++()
		{
			_node = _node->_next;
			return *this;
		}
		self& operator--()
		{
			_node = _node->_prev;
			return *this;
		}
		self operator--(int)
		{
			self tmp = *this;
			--*this;
			return tmp;
		}
		self operator++(int)
		{
			self tmp = *this;
			++* this;
			return tmp;
		}
		bool operator!=(const self& it)
		{
			return _node != it._node;
		}
		Ref operator*()
		{
			return _node->_date;
		}
		Ptr operator->()
		{
			return &_node->_date;
		}
		//成员
		list_node<T>* _node;
	};

在list内部,普通迭代器与const迭代器的原生类型就是:

typedef _list_iterator<T,  T&,  T*> iterator; //这是个普通对象的正向迭代器
typedef _list_iterator<T, const T&, const T*> const_iterator;//const对象的正向迭代器

反向迭代器

我们发现上面实现的迭代器,++操作就是向后迭代、–等操作就是向前迭代,妥妥的正向迭代器,可是反向迭代器嘞?
反向迭代器,也可以按照上面的方法来实现,只不过反向迭代器内部可以封装一个正向迭代器,正向迭代器的++就是反向迭代器的–;正向迭代器的–就是反向迭代器的++;

     //反向迭代器
	template<class Forward_iterators, class Ref, class Ptr>//Forward_iterators是个正向迭代器,那么到底是普通对象的正向迭代器还是const对象的正向迭代器,我们是未知的,全靠程序员利用该模板实例化的时候,给该模板参数传递的类型;Ref、Ptr与上面在正向迭代器中的意义一样
	struct _list_reverse_iterator
	{
		_list_reverse_iterator(const Forward_iterators& it= Forward_iterators())
			:_it(it) {}
		
		typedef _list_reverse_iterator<Forward_iterators, Ref, Ptr> Reself;//反向迭代器类型名字太长了,换个简短点的
		Reself& operator++()//前置
		{
			//正向迭代器的--
			--_it;
			return *this;
		}
		Reself operator++(int)//后置
		{
			Reself tmp(_it);
			--_it;
			return tmp;
		}
		Reself& operator--()//前置
		{
			//正向迭代器的--
			++_it;
			return *this;
		}
		Reself operator--(int)//后置
		{
			Reself tmp(_it);
			++_it;
			return tmp;
		}
		Ref operator*()
		{
			return *_it;
		}
		Ptr operator->()
		{
			return _it.operator->();
		}
		bool operator!=(const Reself&rit)
		{
			return _it != rit._it;
		}
		bool operator==(const Reself& rit)
		{
			return _it==rit;
		}
		//成员是一个正向迭代器;
		Forward_iterators _it;
	};

因此在list内部的我们需要实例化一下普通对象的反向迭代器、和const对象的反向迭代器:

typedef _list_reverse_iterator<iterator, T&, T*> reverse_iterator;//普通对象反向迭代器
typedef _list_reverse_iterator<const_iterator, const T&, const T*> const_reverse_iterator;//const对象反向迭代器
//给_list_reverse_iterator<Forward_iterators ,Ref,Ptr>传递的模板参数不同,就能实例化出不同类型的反向迭代器;

迭代器所有代码

        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);
		}
		reverse_iterator rbegin()
		{
			return reverse_iterator(_head->_prev);
		}
		reverse_iterator rend()
		{
			return reverse_iterator(_head);
		}
		const_reverse_iterator rbegin()const
		{
			return const_reverse_iterator(_head->_prev);
		}
		const_reverse_iterator rend()const
		{
			return const_reverse_iterator(_head);
		}

迭代器总结

迭代器主要有两种形式
1、迭代器要么就是原生指针
2、迭代器要么就是自定义类型对原生指针的封装,模拟指针的行为;

constructor:

list这个容器,难点就在于迭代器,现在我们把迭代器给啃了,后面就好办了;
注意:在每次初始化list的时候都需要创建头节点,为此我们可以把创建头节点的操作封装在一个函数里面;
创建头节点:

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

同时我们可以把该函数放在private作用域下,不对外开放!
无参构造:

list()
{
  empty_init();
}

有参构造(利用n个val来初始化):

 list(int n, const T& val = T())
		{
			empty_init();
			for (int i = 0; i < n; i++)
			{
				push_back(val);
			}
		}

区间构造(可以用任何容器的元素来进行构造,只要可以发生类型转换):

template <class InputIterator>
		list(InputIterator first, InputIterator last)
		{
			empty_init();
			while (first != last)
			{
				push_back(*first);
				first++;
			}
		}

拷贝构造:

list(const list<T>& l)
		{
		//现代写法的拷贝构造
			empty_init();
			list<T> tmp(l.begin(),l.end());
			//先让tmp去调用区间构造创建一个带头双向双向循环链表
			//然后交换tmp对象中_head与*this对象中_head的值;
			//相当于让*this中的_head指向了tmp创建的带头双向循环链表
			//tmp中的_head指向*this创建的带头双向循环链表(只不过只有头而已!);
			swap(tmp);
		}

clear

功能:清除所有节点,但是不清除头节点,让整个链表的size变为0;

	void clear()
		{
			iterator it = begin();
			while (it != end())
			{
				it=erase(it);
			}
			_head->_next = _head->_prev = _head;
		}

~list

析构函数与clear的功能类似,但是析构函数需要释放头节点:

~list()
		{
			clear();
			delete _head;
			_head = nullptr;
		}

front与back

获取头节点元素与尾节点元素

T& front()
		{
			assert(empty() == false);
			return _head->_next->_date;
		}
		const T& front()const
		{
			assert(empty() == false);
			return _head->_next->_date;
		}
		T& back()
		{
			assert(empty() == false);
			return _head->_prev->_date;
		}

		const T& back()const
		{
			assert(empty() == false);
			return _head->_prev->_date;
		}

insert与erase

	//insert过后的pos失效,返回新插入节点的迭代器
       iterator insert(iterator pos, const T& val)
		{
			node* prev = pos._node->_prev;
			node* new_node = new node(val);
			prev->_next = new_node;
			new_node->_prev = prev;
			new_node->_next = pos._node;
			pos._node->_prev = new_node;
			return iterator(new_node);
		}
		
		//erase过后pos迭代器失效!返回原pos迭代器的下一个迭代器
		iterator erase(iterator pos)
		{
			//不能删除_head
			  assert(empty()==false);
				node* prev = pos._node->_prev;
				node* next = pos._node->_next;
				delete pos._node;
				prev->_next = next;
				next->_prev = prev;
				pos = iterator(next);
			return pos;
		}

size与empty与swap

        size_t size()const
		{
			size_t count = 0;
			const_iterator cit = begin();
			while (cit++ != end())
				count++;
				return count;
		}
		bool empty()const
		{
			return (begin() == end());
		}
		void swap(list<T>&l1)
		{
			std::swap(_head,l1._head);
		}
	

pop_back()

        void pop_back()
		{
			assert(empty()==false);
			erase(--end());
		}

总代码:

节点类

   namespace MySpace
   {
    //节点
	template <class T>
	struct list_node
	{
		T _date;
		list_node<T>* _prev;
		list_node<T>* _next;
		list_node(const T& val = T())
			:_date(val), _prev(nullptr), _next(nullptr) {}
	};
   }

正向迭代器类

namespace MySpace
{
//利用一个类来封装list_node<T>*//让这个类作为list<T>的迭代器,然后重载这个类的++、--、*就可以实现迭代器的通用迭代办法
	template<class T, class Ref, class Ptr>
	struct _list_iterator//正向迭代器,底层封装了list_node<T>*
	{
		_list_iterator(list_node<T>* node = nullptr)
			:_node(node) {}

		typedef _list_iterator<T, Ref, Ptr > self;
		self& operator++()
		{
			_node = _node->_next;
			return *this;
		}
		self& operator--()
		{
			_node = _node->_prev;
			return *this;
		}
		self operator--(int)
		{
			self tmp = *this;
			--* this;
			return tmp;
		}
		self operator++(int)
		{
			self tmp = *this;
			++* this;
			return tmp;
		}
		bool operator!=(const self& it)
		{
			return _node != it._node;
		}
		bool operator==(const self& it)
		{
			return !(*this!=it);
		}
		Ref operator*()
		{
			return _node->_date;
		}
		Ptr operator->()
		{
			return &_node->_date;
		}

		//成员
		list_node<T>* _node;
	};
}

反向迭代器类

namespace MySpace
{
//反向迭代器
	template<class Forward_iterators, class Ref, class Ptr>
	struct _list_reverse_iterator
	{
		_list_reverse_iterator(const Forward_iterators& it= Forward_iterators())
			:_it(it) {}
		
		typedef _list_reverse_iterator<Forward_iterators, Ref, Ptr> Reself;//反向迭代器类型名字太长了,换个简短点的
		Reself& operator++()//前置
		{
			//正向迭代器的--
			--_it;
			return *this;
		}
		Reself operator++(int)//后置
		{
			Reself tmp(_it);
			--_it;
			return tmp;
		}
		Reself& operator--()//前置
		{
			//正向迭代器的--
			++_it;
			return *this;
		}
		Reself operator--(int)//后置
		{
			Reself tmp(_it);
			++_it;
			return tmp;
		}
		Ref operator*()
		{
			return *_it;
		}
		Ptr operator->()
		{
			return _it.operator->();
		}
		bool operator!=(const Reself&rit)
		{
			return _it != rit._it;
		}
		bool operator==(const Reself& rit)
		{
			return _it==rit;
		}
		//成员是一个正向迭代器;
		Forward_iterators _it;
	};
}

list类

namespace MySpace
{
//带头双向循环链表
	template<class T>
	class list
	{
	public:
		typedef _list_iterator<T,  T&,  T*> iterator; //这是个普通对象的正向迭代器
		typedef _list_iterator<T, const T&, const T*> const_iterator;//const对象的正向迭代器
		typedef _list_reverse_iterator<iterator, T&, T*> reverse_iterator;//普通对象反向迭代器
		typedef _list_reverse_iterator<const_iterator, const T&, const T*> const_reverse_iterator;//const对象反向迭代器
		typedef list_node<T> node;//节点

		list()
		{
			empty_init();
		}
		list(int n, const T& val = T())
		{
			empty_init();
			for (int i = 0; i < n; i++)
			{
				push_back(val);
			}
		}
		list(const list<T>& l)
		{
			empty_init();
			list<T> tmp(l.begin(),l.end());
			swap(tmp);
		}
		template <class InputIterator>
		list(InputIterator first, InputIterator last)
		{
			empty_init();
			while (first != last)
			{
				push_back(*first);
				first++;
			}
		}
		~list()
		{
			clear();
			delete _head;
			_head = nullptr;
		}
		list<T>& operator=(list<T> l)
		{
			if (this != &l)
			{
				swap(l);
			}
			return *this;
		}
		void push_back(const T& val)
		{
			node* tail = _head->_prev;
			node* new_node = new node(val);
			new_node->_prev = tail;
			tail->_next = new_node;
			new_node->_next = _head;
			_head->_prev = new_node;
		}
		void pop_back()
		{
			assert(empty()==false);
			erase(--end());
		}
		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);
		}
		reverse_iterator rbegin()
		{
			return reverse_iterator(_head->_prev);
		}
		reverse_iterator rend()
		{
			return reverse_iterator(_head);
		}
		const_reverse_iterator rbegin()const
		{
			return const_reverse_iterator(_head->_prev);
		}
		const_reverse_iterator rend()const
		{
			return const_reverse_iterator(_head);
		}
		T& front()
		{
			assert(empty() == false);
			return _head->_next->_date;
		}
		const T& front()const
		{
			assert(empty() == false);
			return _head->_next->_date;
		}
		T& back()
		{
			assert(empty() == false);
			return _head->_prev->_date;
		}

		const T& back()const
		{
			assert(empty() == false);
			return _head->_prev->_date;
		}
		iterator insert(iterator pos, const T& val)
		{
			node* prev = pos._node->_prev;
			node* new_node = new node(val);
			prev->_next = new_node;
			new_node->_prev = prev;
			new_node->_next = pos._node;
			pos._node->_prev = new_node;
			return iterator(new_node);
		}
		iterator erase(iterator pos)
		{
			    //不能删除_head
			    assert(empty()==false);
				node* prev = pos._node->_prev;
				node* next = pos._node->_next;
				delete pos._node;
				prev->_next = next;
				next->_prev = prev;
				pos = iterator(next);
			return pos;
		}
		size_t size()const
		{
			size_t count = 0;
			const_iterator cit = begin();
			while (cit++ != end())
				count++;
				return count;
		}
		bool empty()const
		{
			return (begin() == end());
		}
		void swap(list<T>&l1)
		{
			std::swap(_head,l1._head);
		}
	
		void clear()
		{
			iterator it = begin();
			while (it != end())
			{
				it=erase(it);
			}
			_head->_next = _head->_prev = _head;
		}

	private:
		list_node<T>* _head;
		void empty_init()
		{
			_head = new node;
			_head->_next = _head->_prev = _head;
		}
	};
}
  • 23
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 21
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

南猿北者

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

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

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

打赏作者

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

抵扣说明:

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

余额充值