会使用STL中的list并且模拟实现list

如何使用list,看如下代码

#include<iostream>
#include<list>
#include<stdlib.h>
#include<functional>
using namespace std;
void PrintList(list<int>& l1)
{
	list<int>::iterator it = l1.begin();
	while (it != l1.end())
	{   
		cout << *it << " ";
		it++;
	}

	cout << endl;
}
int main()
{
	list<int>l1;
	l1.push_back(2);
	l1.push_back(2);
	l1.push_back(3);
	l1.push_back(1);
	PrintList(l1);
	l1.remove(4);//删除不存在的   不报错
	l1.remove(2);//删除存在的     不报错
	PrintList(l1);
	list<int> l2(5, 1);
	PrintList(l1);
	PrintList(l2);
	list<int>::iterator it = l1.begin();
	/*while (it != l1.end())//本意想删除刚才插入的所有元素       出错迭代器失效
	{   if(*it)
		l1.erase(it);
         it++;
	}*/
	while (it != l1.end())
	{
		if (*it)
		{
			it = l1.erase(it);//可看出库里面的erase有一个返回值 ,返回的是删除位置下一个位置的迭代器
		}
		else
		{
			it++;
		}
	}
	PrintList(l1);
	l1.sort();//升序排
	l1.unique();//去重,也就是去除连起来的相同的元素   一般和排序sort结合着用
	PrintList(l1);
	l1.reverse();
	PrintList(l1);
	l1.sort(greater<int>());//greater是降序,less是升序   头文件是<functional>
	cout << endl;
	////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	//l1.remove(4);//删除不存在的   不报错
	//l1.remove(2);//删除存在的     不报错
	//PrintList(l1);
	//l1.erase(l1.begin());//删除存在的    不报错
	//PrintList(l1);
	//l1.erase(l1.end());//删除不存在的    报错     
	//PrintList(l1);
	system("pause");
	return 0;
}

注意remove和erase的区别:
remove删除,给一个值,有就删除,没有就不删除
erase 删除,给一个位置,找到就删除,找不到即空位置报错

自己实现的list

#include<iostream>
#include<assert.h>
using namespace std;
template <class T>
struct  MyListNode
{
	T _data;
	MyListNode<T>* _next;
	MyListNode<T>* _prev;
	MyListNode(const T& x)
		: _data(x)
		, _next(NULL)
		, _prev(NULL)
	{
	}
};
template<class T,class Ref,class Ptr>
class ListIterator//迭代器是一个类,对结点指针进行封装,通过对类重载operator++,--,*,->,向一个指针一样遍历所有容器,访问,修改,都有统一的方式,学习成本低会用迭代器访问list就会用它访问vector
{
public:
	typedef MyListNode<T> Node;
	typedef ListIterator<T, Ref, Ptr>Self;
	ListIterator(Node* node)
		:_node(node)
	{}
	Ref operator*()
	{
		return _node->_data;
	}
	Ptr operator->()  
	{
		return &(_node->_data);
	}
	Self& operator++()//前置++
	{
		_node = _node->_next;
		return *this;
	}
	Self operator++(int)
	{
		Self tmp(*this);//掉拷贝构造    //Self tmp(_node);//掉构造
		_node = _node->_next;
		return tmp;//此处有一次拷贝构造
	}
	Self& operator--()
	{
		_node = _node->_prev;
		rturn *this;
	}
	Self operator--(int)
	{
		Node* cur = _node;
		_node = _node->_prev;
		return Self(cur);//这里相对上面实现的operator++(int)少了一次拷贝构造,优化
	}
	bool operator!=(Self& s)
	{
		return _node != s._node;
	}
	bool operator==(Self& s)
	{
		return _node == s._node;
	}
	Node* _node;

};
template <class T>
class MyList
{
public:
	typedef MyListNode<T> Node;
	typedef ListIterator<T, T&, T*> Iterator;
	typedef ListIterator<T, const T&, const T*> ConstIterator;
	MyList()
	{
		_head = GetNode(T());//用匿名对象初始化
		_head->_next = _head;
		_head->_prev = _head;
	    
	}
	~MyList()
	{
		Clear();
		delete _head;
		_head = NULL;
	}
	void Clear()
	{
		Iterator it = Begin();
		while (it != End())
		{
			Node* del = it._node;
			++it;
			delete del;
		}
		_head->_next = _head;
		_head->_prev = _head;
	}
	void PushBack(const T&x)
	{
		Node* tail = _head->_prev;
		Node* newNode = GetNode(x);
		tail->_next = newNode;
		newNode->_prev = tail;
		newNode->_next= _head;
		_head->_prev = newNode;
	}
	void PopBack()
	{
		
		Erase(--End());
	}
	void PushFront(const T& x)
	{
		Insert(Begin(),x);
	}
	void PopFront()
	{
		Erase(Begin());
	}
	bool Empty()
	{
		return _head->_next = _head;
	}
	Iterator Insert(Iterator pos, const T&x)
	{
		assert(pos._node);
		Node* tmp = GetNode(x);
		Node* prev = pos._node->_prev;
		Node* next = pos._node->_next;
		prev->_next = tmp;
		tmp->_prev = prev;
		tmp->_next = next;
		next->_prev = tmp;
		return tmp;
	}
	
	Node* GetNode(const T& x)
	{
		return new Node(x);
	}
	Iterator Erase(Iterator pos)//注意erase返回的是下一个位置的迭代器
	{
		assert((pos != End()) && (pos._node));
		Node* prev = pos._node->_prev;
		Node* next = pos._node->_next;
		delete pos._node;
		prev->_next = next;
		next->_prev = prev;
		return Iterator(next);//也可以是return next;隐式类型转换
	}

	Iterator Begin()
	{
		return Iterator(_head->_next);//也可以为return _head->_next   隐式类型转换
	}
	Iterator End() 
	{
		return Iterator(_head);
	}
	ConstIterator Begin()const
	{
		return ConstIterator(_head->_next);
	}
	ConstIterator End() const//相当于返回值是const T* 也就是说明迭代器指向的数据不能被改
	{
		return ConstIterator(_head);
	}
	//去重
	void Unique()//思路,两个迭代器,一个前,一个后,如果不同,同时向后走,相同删除一个并且走一步,另一个不动,直到快的那个结束
	{
		Iterator first = Begin();
		
		if (first == End())//没有结点,不用去重
			return;
		Iterator fast = Iterator(first._node->_next);
		while (first != End())
		{    
			if (*first == *fast)
			{
				fast = Erase(fast);
			}
			else
			{
				++first;
				++fast;
			}
		}
	}
	Iterator Find(const T&x)//Find返回迭代器,不能返回指针  暴露细节  
	{
		Node* cur = _head->_next;
		while (cur != _head)
		{
			if (cur->_data == x)
			{
				return Iterator(cur);
				cur = cur->_next;
			}
		}
		return Iterator(_head);//没找到返回头  不存在的迭代器
	}
	void Remove(const T& x)//删除
	{
		Iterator first = Begin();
		while (first != End())
		{
			if (*first == x)
			{
				first=Erase(first);
			}
			else
			{
				++first;
			}
		}
	}
private:
	Node* _head;

};

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//void PrintList(const MyList<int>& l1)//参数有const修饰,只需实现如下有const修饰的Begin()和End()即可,通过编译。思考?为什莫还要ConstIterator呢?
//原因在于,虽然这样可以编译通过,但是普通迭代器,*it数据可以被改变,但是我们之所以加const就是不希望被改变。因此有了ConstIterator
//{
//	MyList<int>::Iterator it = l1.Begin();
//	while (it != l1.End())
//	{
//		*it = 10;//此处不报错  可以被改变
//		cout << *it << " ";
//		it++;
//	}
//
//	cout << endl;
//}
//Iterator Begin()const
//{
//	return Iterator(_head->_next);//也可以为return _head->_next   隐式类型转换
//}
//Iterator End() const
//{
//	return Iterator(_head);
//}

/////	/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void PrintList(const MyList<int>& l1)
{
	MyList<int>::ConstIterator it = l1.Begin();//ConstIterator迭代器 
	while (it != l1.End())
	{
		//*it = 10;//本句会报错,因为是const迭代器 迭代器指向数据不能被改
		cout << *it << " ";
		it++;
	}

	cout << endl;
}

int main()
{
		MyList<int>l1;
		l1.PushBack(1);
		l1.PushBack(3);
		l1.PushBack(3);
		l1.PushBack(4);
		l1.PushBack(3);
		PrintList(l1);
		l1.Unique();
		l1.Remove(3);
		PrintList(l1);
		l1.Reverse();
		PrintList(l1);
		MyList<int>::Iterator it = l1.Begin();
		/*while (it != l1.End())//STL中删除存在迭代器失效    因此Erase删除必须用一个迭代器接收,返回的是下一个迭代器  
		{
			if (*it % 2 == 0)
			{
				it=l1.Erase(it);
			}
			else
			{
				++it;
			}
		}*/
		//while (it != l1.End())//如果我就想这样用,怎末办?怎样改进Erase
		//{
		//	if (*it % 2 == 0)
		//	{
		//		l1.Erase(it);
		//	}
		//	++it;
		//}
		//PrintList(l1);

/////////////////////////////////////////////////一个面试题 /////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
		//Iterator Erase(Iterator& pos)//注意此处给的是引用,因为删除pos位置迭代器,此时pos位置(也就是it)已经被删除,如果继续++it就会迭代器失效
		//{                            //但是现在我们给pos赋值为前一个迭代器 ,加加指向后面便可解决这个问题
		//	assert((pos != End()) && (pos._node));
		//	Node* prev = pos._node->_prev;
		//	Node* next = pos._node->_next;
		//	delete pos._node;
		//	prev->_next = next;
		//	next->_prev = prev;
		//	pos = prev;
		//	return Iterator(next);//也可以是return next;隐式类型转换
		//}
		system("pause");
		return 0;
}

上面自己实现的list,有一句MyList<int>::ConstIterator it = l1.Begin()没有自己合成拷贝构造,用自动生成的那个,浅拷贝。为什莫不出错。。
以前出错的原因是:多个指针指向一块空间析构时被析构了多次,而本次不会出错因为迭代器不用释放节点,迭代器不析构这个结点,析构结点是链表做的是。迭代器只负责访问,修改遍历(也就是要两个迭代器指向同一位置,才能修改),不释放。


猜你喜欢

转载自blog.csdn.net/baidu_37964044/article/details/79797351