STL--> list 双向循环链表容器 接口使用及介绍。 模拟实现 STL list容器

使用STL vector 接口:

#include 
#include 

using namespace std;

void TestVector( )
{
	
	vector v1;

	v1.push_back( 1 ); 
	v1.push_back( 2 ); 
	v1.push_back( 3 ); 
	v1.push_back( 4 );	
	
	PrintVector( v1 );
	
	vector v2( 3, 10 );
	PrintVector( v2 );
}

int main( )
{
	TestVector( );

	return 0;
}


//封装是为了复用,调用这个函数即可,不用每次都写打印代码
void PrintVector( vector& v1 )//引用           //加 const 编译不通过   如果要编译通过 1.普通迭代器(可读,可写)   2.const 迭代器(可读)  3.反向迭代器(反着遍历)
{	
	//迭代器 是 类似指针的一个对象  ->   和智能指针相似     
	//[begin, end) 迭代器是 左闭右开 区间 

	vector::iterator it/*迭代器对象*/;			//如果用const_iterator   则   ++(*it)  会报错, 因为不能给常量赋值
	it = v1.begin( );

	while ( v1.end( ) != it )
	{
		//1.打印
		cout << *it << " ";
		++it;

		//2.打印奇数
		//if ( 0 != *it % 2 )
		//{
		//	cout << *it << " ";
		//}
		/*++it;*/

		//3.每个数加 1
		//++(*it);
		//++it;
	}

	cout << endl;

	//反向迭代器 是 倒着走
	vector::const_reverse_iterator rIt = v.rbegin( );

	while ( v.rend() != rIt )
	{
		cout << *rIt << " ";

		++rIt;
	}

	cout << endl;
}

list:

#include 
#include 

using namespace std;

void TestList( );
void PrintList( list& l );

int main( )
{
	TestList( );

	return 0;
}

void TestList( )
{
	list l1;

	l1.push_back( 1 );
	l1.push_back( 2 );
	l1.push_back( 3 );
	l1.push_back( 4 );

	list l2( 5, 1 );						//带值的初始化
}

void PrintList( /*const*/list& l )
{
	list::/*const_*/iterator it = l.begin( );

	while ( l.end( ) != it )
	{
		cout << *it << " ";
		/* *it = 10; *///如果是	const迭代器 则不能赋值
		++it;
	}

	cout << endl;
}


模拟实现:STL 中 名字为 list, 我们模拟实现名字为 List

:

//链表的四次实现
//1.C ->	 基本实现和面试题
//2.C++ -> 面向对象  C 和 C++区别  深拷贝
//3.C++ -> 泛型编程  +  T  -- string
//4.数据结构 -- STL
//搜索 ctrl + f  -> 快捷键查找F3 -> 倒着搜索 shift + F3
//名称 小写加下划线

#pragma once//防止重定义


#include "Iterator.h"//为了实现 List 反向迭代器


template
struct __ListNode
{
	T _data;
	__ListNode* _next;
	__ListNode* _prev;
	
	__ListNode( const T& x )
		:_data( x )
		,_next( NULL )
		,_prev( NULL )
	{}
};

//迭代器   是一个 类  通过 运算符重载  使它像指针一样使用
//T T& T*   有了 T 为什么 还有传 T&, T*  ,为了实现 const迭代器
//T const T&  const T*
template
struct __ListIterator   // sizeof(__ListIterator)  == 4  因为它里面还是一个指向节点的指针,只是通过封装1让它变为新的类型, 大小不变,为4
{
	typedef __ListNode Node;
	typedef __ListIterator Self;
	typedef Ref Reference;//反向迭代器
	typedef Ptr Pointer;//反向迭代器

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

	Ref operator*( )//1.出了作用域存在,所以传&。而且为了效率,  如果不传引用,  string对象, 深拷贝。 2.  引用是为了可以更改数据
	{
		return _node->_data;
	}

	const Ref operator*( )//const 迭代器 中 用 const 修饰 Ref即可。
	{
		return _node->_data;
	}

	Ptr operator->( )
	{
		return &_node->_data;
	}

	Self& operator++( )//前置++			//注意后置 前置的区别
	{
		_node = _node->_next;

		return *this;
	}	
	
	Self operator++( int )//后置++  不能给& 因为出了作用域对象不存在,不能给引用
	{
		Self tmp( _node );//构造                          1
		//Self tmp( *this );//拷贝构造                    2
		_node = _node->_next;

		return tmp;
	}//   1 or 2 时 构造 or 拷贝构造, 然后 return 时, 再拷贝构造个临时对象返回。

	Self& operator--( )
	{
		_node = _node->_prev;

		return *this;
	}
		
	Self operator--( int )
	{
		Node* cur = _node;
		_node = _node->_prev;

		return Self( cur );//先构造出一个对象,再拷贝构造出临时对象返回,但是他们是在返回步骤的一个表达式里,编译器会进行优化 -> 不会先构造再拷贝构造而是  直接构造临时对象   作为返回值,  所以 这里的代码 比 后置++实现的好.
	}

	bool operator!=( const Self& s ) const
	{
		return /*this->*/_node != s._node;//指针全是通过->调用,调用函数也是->。  对象全是 通过.调用
	}

	Node* _node;
};

template
class List
{
	typedef __ListNode Node;

public:
	typedef __ListIterator Iterator;
	typedef __ListIterator ConstIterator;//实现 const 迭代器
	typedef ReverseIterator ConstReverseIterator;//注意这一句和后一句顺序不能颠倒, 否则, 最后一句 的ReverseIterator 已经被 typedef 这里就用不了了
	typedef ReverseIterator ReverseIterator;
	//此时只能实现 List 的反向迭代器, Vector的反响迭代器不能这样实现, 需要类型萃取才可以!


	Node* GetNode( const T& x )
	{
		return Node* node = new Node( x );
	}

	List( )
	{
		_head = GetNode( T( )/*匿名对象*/ );
		_head->_next = _head;
		_head->_prev = _head;
	}

	~List( )
	{
		Clear( );//清掉数据 。 but 析构还没完, 除了清掉数据还要把整个链表全销毁了

		delete _head;
		_head = NULL;
	}

	Iterator Begin( )//const对象不能调用 普通成员函数
	{
		return Iterator( _head->_next );
	}	
		
	//不能这样写
	//Iterator Begin( ) const
	//{
	//	return Iterator( _head->_next );
	//}	
	//const 成员函数 , 被 const 对象调用  -->  不可修改
	//应该返回 const 迭代器
	ConstIterator Begin( ) const
	{
		return ConstIterator( _head->_next );
	}	
	
	Iterator End( )
	{
		return Iterator( _head );
	}	

	ConstIterator End( ) const
	{
		return ConstIterator( _head );
	}

	 ReverseIterator RBegin( )//如图, 正向迭代器和反向迭代器的 begin 和 end 完全对应起来!  也由此图理解解引用  -->  为什么取前一个位置数据。   Node*  -->  正向迭代器  -->  反向迭代器
	 {
		return ReverseIterator( End( ) );
	 }

	 ReverseIterator REnd( )
	 {
		return ReverseIterator( Begin( ) );
	 }

	 ConstReverseIterator RBegin( ) const
	 {
		return ConstReverseIterator( End( ) );
	 }

	 ConstReverseIterator REnd( ) const
	 {
		return ConstReverseIterator( Begin( ) );
	 }

	void PushBack( const T& x )
	{
		//我们以前实现方法
		//Node* tail = _head->_prev;
		//Node* tmp = GetNode( x );


		//tail->_next = tmp;
		//tmp->_prev = tail;

		//tmp->_next = _head;
		//_head->_prev = tmp;

		//STL 实现方法
		Insert( End( ), x );
	}

	void PushFront( const T& x )
	{
		Insert( Begin( ), x );
	}

	void PopBack( )
	{
		//assert( !Empty( ) );//不为空才行,   否则不让你删除

		//Node* tail = _head->_prev;
		//Node* prev = tail->_prev;
		//
		//delete tail;

		//prev->_next = _head;
		//_head->_prev = prev;
		
		Erase( _head->_prev );
		Erase( --End( ) );
	}

	void PopFront( )
	{
		Erase( Begin( ) );
	}

	void Clear( )
	{
		Iterator it = Begin( );//注意不用写为: List::Iterator  因为这是类里面, Iterator就是属于这个类域的

		while ( End( ) != it )
		{
			Node* del = it._node; //注意  为.  而不是  ->
			++it;

			delete del;
		}

		_head->_next = _head;		//别忘了 ,还需要重置
		_head->_prev = _head;
	}

	Iterator Find( const T& x )
	{
		//Node* cur = _head->_next;

		//while ( _head != cur )
		//{
		//	if ( x == cur->_data )
		//	{
		//		return cur;//隐式类型转换, Iterator为单参数构造函数。 用 cur 构造临时对象发货
		//		//return Iterator( cur );
		//	}
		//	else
		//	{
		//		cur = cur->_next;
		//	}
		//	//如string s = "1111", 一个是c风格字符串, 一个是字符串, 即用了 隐式类型转换

		//	return _head;
		//}

		Iterator it = Begin( );  //成员函数可以调用其他成员函数 是因为有隐含this指针

		while ( End( ) != it )
		{
			if ( x == *it )
			{
				return it;
			}
			else
			{
				++it;
			}
		}

		return it;							//这里返回的 是 End这个位置
	}

	//在 pos 的前面进行插入
	void Insert( Iterator pos, const T& x )
	{
		assert( pos._node );//pos这个迭代器中的结点不能为空

		Node* next = pos._node;
		Node* prev = next->_prev;
		
		Node* cur = new Node( x );

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

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

	//测试考虑到:1。正常情况, 2.边界情况(头,尾,空)
	//但这种情况会引起我们下面提出的问题,迭代器失效, 所以这种方案不好, 采用下面的方案
	//void Erase( Iterator pos )
	//{
	//	assert( (End( ) != pos) && (NULL != pos._node) );//等于 End( )  相当于删除 头节点  -->   1.没有结点情况  2.给了非法的位置 ,如有多个结点,你却给了我头节点。

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

	//	delete del;

	//	prev->_next = next;
	//	next->_prev = prev;
	//}
		
	Iterator Erase( Iterator pos )
	{
		assert( (End( ) != pos) && (NULL != pos._node) );

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

		delete del;

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

		//解决迭代器失效方法, 返回 删除位置下一个位置的迭代器
		return next;							//单参数构造函数 进行 隐式转换
	}

	bool Empty( )
	{
		return _head == _head->_next;
	}

	//[)
	//模板类中成员函数也可以给成 模板函数
	template 
	void Assign( InputIterator first, InputIterator last )
	{
		Clear( );

		while ( first != last )
		{
			PushBack( *first );
		
			++first;
		}
	}

protected:
	Node* _head;
};


struct AA
{
	int _a1;
	int _a2;
};


template