C++ STL::list常用操作及底层实现(中2)——实现list常用操作之删除(erase、remove、pop_front、pop_back、clear)


上一篇我们介绍了插入的常用操作,本文介绍删除的相关操作。

1.erase():按链表迭代器删除

它有两种函数形式:
格式1:iterator erase (iterator position)
格式2:iterator erase (iterator first, iterator last)
下面分别介绍两种形式的用法,及实现这两种格式。

1.1函数格式1:iterator erase (iterator position)

  • 解释:删除position位置的元素,并返回被删除的元素的下一个元素的迭代器
  • 举例:有一个链表l:1<->2<->3。执行erase(l.begin())后链表变为2<->3,返回2位置的迭代器。

我的实现:

template <typename T>
Iterator<T> Mylist<T>::erase(Iterator<T> it)
{
	ListNode<T> *cur = it.current;
	for (Iterator<T> i = this->Begin(); i != this->End(); ++i){
		if (i == it){
			it.current->rightlink->leftlink = it.current->leftlink;
			it.current->leftlink-> rightlink = it.current->rightlink;
			it++;
			delete cur;

			break;
		}
	}
	return it;
}

1.2函数格式2:iterator erase (iterator first, iterator last)

  • 解释:删除[first,last)位置的元素,并返回被删除的元素的下一个元素的迭代器,也就是last迭代器
  • 举例:有一个链表l:1<->2<->3。执行erase(l.begin(),–l.end())后链表变为3,返回3位置的迭代器。
  • 使用注意:当first = last时,不删除元素,但是返回的迭代器是last对应的位置。

我的实现:
通过调用erase格式1形式来实现。
Notes:在STL::list实现中,当first = begin(),last = end()时,它调用了clear()函数,所以我也按照它来实现。其实我认为直接用while调用第一种格式的erase也能实现,为什么STL要这么做我现在也不太明白,如果有大佬知道,希望大佬能告知,评论也行,私信也可以。

template <typename T>
Iterator<T> Mylist<T>::erase(Iterator<T> first, Iterator<T> last)
{
	if (first == this->Begin() && last == this->End()){	
		Clear();// erase all and return fresh iterator
		return last;
	}
	else{	// erase subrange
		while (first != last)
			first = erase(first);

		return first;
	}
}

2.remove():按值执行删除操作

函数格式:void remove (const value_type& val)

  • 解释:删除链表中值为val的元素
  • 举例:有一个链表l:1<->2<->3<->1。执行remove (1)后链表变为2<->3

我的实现:
通过调用第一种格式erase()来实现。

template <typename T>
void Mylist<T>::Remove(const T& _data)
{
	for (Iterator<T> i = this->Begin(); i != this->End();){
		if (*i == _data){
			i = erase(i);
		}
		else{
			++i;
		}
	}
}

3. pop_front、pop_back:删除链表头和链表尾的元素

  • 解释:pop_front删除链表头元素;pop_back删除链表尾部数据。
  • 举例:有一个链表l:1<->2<->3<->1。执行pop_front ()后链表变为2<->3<->1;再执行pop_back(),链表变为2<->3
    我的实现:
template <typename T>
void Mylist<T>::Pop_front()
{
	erase(this->Begin());
}
template <typename T>
void Mylist<T>::Pop_back()
{
	erase(--this->End());
}

4. clear:清除链表所有元素

  • 解释:清除链表中的所有元素
  • 有一个链表l:1<->2<->3<->1。执行clear ()后链表变为空

我的实现:

template <typename T>
void Mylist<T>::Clear()
{
	ListNode<T> *cur = first->rightlink;//保存fisrt的下一个节点

	first->leftlink = first;//first的左指针指向自己
	first->rightlink = first;//first的右指针指向自己

	/*释放节点*/
	while (cur != first){
		ListNode<T> *tmp = cur;
		cur = cur->rightlink;
		delete tmp;
	}
}

5.完整代码(包括插入和删除)

Mylist.h

#ifndef _MY_LIST_H
#define _MY_LIST_H

template <typename T>
class Mylist;

template <typename T>
class Iterator;

//定义双向链表的结点类
template <typename T>
class ListNode
{
	friend class Mylist<T>;//Mylist类为ListNode类的友元,从而可以访问其私有成员
	friend class Iterator<T>;//迭代器类Iterator为ListNode类的友元,从而可以访问其私有成员
private:
	T data;
	ListNode<T> * leftlink;
	ListNode<T> * rightlink;

	ListNode() :leftlink(nullptr), rightlink(nullptr){};
	ListNode(T _data) :data(_data), leftlink(nullptr), rightlink(nullptr){}
};


//定义双向链表类
template <typename T>
class Mylist
{
public:

	Mylist();
	~Mylist();

	Iterator<T> Begin();
	Iterator<T> End();
	/********************插入**********************/
	Iterator<T> Insert(Iterator<T> it, const T& _data);//插入数据
	Iterator<T> Insert(Iterator<T> it, int n, const T& _data);//插入数据
	template <class Iter>
	Iterator<T> Insert(Iterator<T> it, Iter first, Iter last);//插入数据

	void Push_front(const T& _data);//在表头插入
	void Push_back(const T& _data);//在末尾插入

	void Splice(Iterator<T> it, Mylist<T> & x);
	void Splice(Iterator<T> it, Mylist<T> & x,Iterator<T> i);
	void Splice(Iterator<T> it, Mylist<T> & x, Iterator<T> first, Iterator<T> last);

	/*******************删除**********************/
	Iterator<T> erase(Iterator<T> it);
	Iterator<T> erase(Iterator<T> first, Iterator<T> last);

	void Remove(const T& _data);//删除数据

	void Pop_front();//删除表头元素
	void Pop_back();//删除最后一个元素

	void Clear();//删除全部数据
	
	bool Empty();
private:
	ListNode<T> * first;
};

//定义迭代器iterator
template <typename T>
class Iterator
{
	friend class Mylist<T>;//Mylist类为Iterator类的友元,从而可以访问其私有成员
public:
	Iterator() :current(nullptr){}
	Iterator(ListNode<T> *& node) :current(node){}

	//重载解引用符*
	T& operator*()
	{
		return this->current->data;
	}

	//重载前缀自加运算符++
	Iterator<T>& operator++()
	{
		this->current = this->current->rightlink;
		return *this;
	}
	//重载后缀自加运算符++
	Iterator<T> operator++(int)
	{
		Iterator<T> tmp = *this;
		(*this).current = (*this).current->rightlink;

		return tmp;
	}

	//重载前缀自减运算符--
	Iterator<T>& operator--()
	{
		this->current = this->current->leftlink;
		return *this;
	}
	//重载后缀自加运算符--
	Iterator<T> operator--(int)
	{
		Iterator<T> tmp = *this;
		(*this).current = (*this).current->leftlink;

		return tmp;
	}

	//重载不等比较运算!=
	bool operator!=(const Iterator<T>& it)
	{
		return this->current != it.current;
	}
	//重载等于比较运算==
	bool operator==(const Iterator<T>& it)
	{
		return this->current == it.current;
	}

	//重载->
	T* operator->()
	{
		return &(this->current->data);
	}

private:
	ListNode<T> * current;//节点指针
};



/***************************构造和析构函数*************************/
template <typename T>
Mylist<T>::Mylist()
{
	first = new ListNode<T>;//生成一个表头结点,它里面不带数据
	first->leftlink = first->rightlink = first;//左右都指向自己
}
template <typename T>
Mylist<T>::~Mylist()
{
}


/*********************Begin()和End()返回链表头和尾的迭代器***********************/
template <typename T>
Iterator<T> Mylist<T>::Begin()
{
	return Iterator<T>(first->rightlink);
}
template <typename T>
Iterator<T> Mylist<T>::End()
{
	return Iterator<T>(first);
}

/***************************插入数据Insert()*****************************/
template <typename T>
Iterator<T> Mylist<T>::Insert(Iterator<T> it, const T& _data)
{
	ListNode<T> *newNode = new ListNode<T>(_data);//生成一个节点

	//1.确定插入节点的指向
	newNode->leftlink = it.current->leftlink;
	newNode->rightlink = it.current;
	//2.改变迭代器it指向节点的指向
	it.current->leftlink = newNode;
	//3.改变插入节点的前一个节点指向
	newNode->leftlink->rightlink = newNode;

	return  Iterator<T>(newNode);
}
template <typename T>
Iterator<T> Mylist<T>::Insert(Iterator<T> it, int n, const T& _data)
{
	for (; n>0; --n)
		it = Insert(it, _data);
	return it;
}
template <typename T>
template <class Iter>
Iterator<T> Mylist<T>::Insert(Iterator<T> it, Iter first, Iter last)
{
	Iter _first = first;

	for (; last != first; ++first){
		Insert(it, *first);
	}
	for (; last != _first; ++_first){
		it--;
	}
	return it;
}
/***************************插入数据push_front()\push_back()****************************/
template <typename T>
void Mylist<T>::Push_front(const T& _data)
{
	Insert(this->Begin(),_data);
}
template <typename T>
void Mylist<T>::Push_back(const T& _data)
{
	Insert(this->End(), _data);
}
/***************************插入数据Splice()****************************/
template <typename T>
void Mylist<T>::Splice(Iterator<T> it, Mylist<T> & x)
{
	Splice(it,x,x.Begin(),x.End());
}
template <typename T>
void Mylist<T>::Splice(Iterator<T> it, Mylist<T> & x, Iterator<T> i)
{
	Iterator<T> tmp = i;
	//检测i是否为x的迭代器
	for (Iterator<T> ite = x.Begin(); ite != x.End(); ite++){
		if (ite == i){
			Splice(it, x, i, ++tmp);
			break;
		}
	}
}
template <typename T>
void Mylist<T>::Splice(Iterator<T> it, Mylist<T> & x, Iterator<T> first, Iterator<T> last)
{
	Iterator<T> _first = first;

	bool InList = false;
	bool OneList = false;

	//1.当x和this不是同一个,并且x不为空时,执行操作
	if (this != &x && !x.Empty()){
		//2.检测first是不是x的迭代器
		for (Iterator<T> tmp = x.Begin(); tmp != x.End(); tmp++){
			if (tmp == first){
				InList = true;
				break;
			}
		}
		//3.判断last是否>first,并且判断first到last是不是一条完整的链表
		while (InList && first!=last && ++_first != x.End()){
			if (_first.current == last.current){
				OneList = true;
				break;
			}
		}
		if (first != last && _first == x.End() && _first.current == last.current)
			OneList = true;

		//4.splice操作
		if (InList == true && OneList == true){
			ListNode<T> *lastNodePre = last.current->leftlink;

			first.current->leftlink->rightlink = last.current;
			last.current->leftlink = first.current->leftlink;

			first.current->leftlink = it.current->leftlink;

			it.current->leftlink->rightlink = first.current;
			it.current->leftlink = lastNodePre;

			lastNodePre->rightlink = it.current;
		}
	}
}

/***************************按迭代器删除数据erase()****************************/
template <typename T>
Iterator<T> Mylist<T>::erase(Iterator<T> it)
{
	ListNode<T> *cur = it.current;
	for (Iterator<T> i = this->Begin(); i != this->End(); ++i){
		if (i == it){
			it.current->rightlink->leftlink = it.current->leftlink;
			it.current->leftlink-> rightlink = it.current->rightlink;
			it++;

			delete cur;
			break;
		}
	}
	return it;
}
template <typename T>
Iterator<T> Mylist<T>::erase(Iterator<T> first, Iterator<T> last)
{
	if (first == this->Begin() && last == this->End()){	
		Clear();// erase all and return fresh iterator
		return last;
	}
	else{	// erase subrange
		while (first != last)
			first = erase(first);

		return first;
	}
}

/***************************按数值删除数据:remove()****************************/
template <typename T>
void Mylist<T>::Remove(const T& _data)
{
	for (Iterator<T> i = this->Begin(); i != this->End();){
		if (*i == _data){
			i = erase(i);
		}
		else{
			++i;
		}
	}
}

/***************************Pop_front、Pop_back****************************/
template <typename T>
void Mylist<T>::Pop_front()
{
	erase(this->Begin());
}
template <typename T>
void Mylist<T>::Pop_back()
{
	erase(--this->End());
}
/***************************删除全部数据Clear()****************************/
template <typename T>
void Mylist<T>::Clear()
{
	ListNode<T> *cur = first->rightlink;//保存fisrt的下一个节点

	first->leftlink = first;//first的左指针指向自己
	first->rightlink = first;//first的右指针指向自己

	/*释放节点*/
	while (cur != first){
		ListNode<T> *tmp = cur;
		cur = cur->rightlink;
		delete tmp;
	}
}

template <typename T>
bool Mylist<T>::Empty()
{
	return first->rightlink == first;
}
#endif

好了,list的删除操作就完成了,下一篇文章将实现list的一些其他的操作。

如果有疑问,欢迎评论区下方留言;本人水平有限 ,如有错误,也欢迎在评论区下方批评指正。若是喜欢本文,就帮忙点赞吧!

系列文章链接:
C++ STL::list常用操作及底层实现(上)——实现list迭代器

C++ STL::list常用操作及底层实现(中1)——实现list常用操作之插入(insert、push_front、push_back、splice)

C++ STL::list常用操作及底层实现(中2)——实现list常用操作之删除(erase、remove、pop_front、pop_back、clear)

C++ STL::list常用操作及底层实现(下)——实现list其他常用操作(reverse、assign、front、back)

  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值