• 迭代器辅助函数


    c++标准程序提供了三个辅助函数,分别是advance(), distance(),iter_swap();通过这三个辅助函数可以增强迭代器的能力,比如 list 也具备了向前跳跃 n个元素的能力了。

    Advance()

    advance()可以将迭代器的位置为增加,增加的幅度由参数决定,即使迭代器一次性前进或后退多个元素。
    函数声明如下:
    void advance(InputIterator &pos, Dist n);
    1.对Bidirectional 迭代器 和Random Access迭代器而言, n可以为负值,表示向后跳跃。
    2.Dist 是个template型别,通常应该是个整数型别。
    3.advance()并不检查迭代器是否超过序列的end(),所以存在一个潜在的危险:如果对序列尾端执行"operator++"操作将会导致未定义的操作行为。

    需要特别说明的是,此函数总能根据迭代器类型(category)采用最佳方案,这个归于迭代器特征(iterator traits)的应用。面对Random Access迭代器,此函数只是简单的执行 pos += n。对于其他的类型的迭代器则执行 ++pos n次,后文再介绍iterator traits。
    /****************************************************************
    *函数名称:AdvanceInstance
    *功    能:advance函数使用示范
    *作    者:Jin
    *日    期:2016年5月29日
    ****************************************************************/
    void AdvanceInstance()
    {
    	typedef list<int> IntList;
    	IntList Collector;
    	//insert 0 1 2 3 4 5 6 7 8 9
    	for (int i = 0; i < 10; i++)
    	{
    		Collector.push_back(i);
    	}
    
    	IntList::iterator pos = Collector.begin();
    
    	//output: 0
    	cout << "fist element: " << *pos << endl;
    
    	//step three element forward 
    	advance(pos, 3);
    	//output: 3
    	cout << "step three element forward: " << *pos << endl;
    	
    	advance(pos, -2);
    	//output: 1
    	cout << "step two element backward: " << *pos << endl;
    }

    Distance()

    函数distance用来处理两个迭代器之间的距离,函数声明如下:
    Dist distance(_InIt _First, _InIt _Last);
    1.传回两个input迭代器_First,_Last之间的距离。
    2.两个迭代器都必须是指向同一个迭代器。
    3.如果不是Random Access迭代器,则_Last迭代器必须和_First相同或在_First之后,否则会导致未定义行为
    4.返回值的Dist型别由迭代器决定:iterator_traits<InputIterator>::difference_type

    advance函数类似,此函数能根据迭代器类型(category)采用最佳方案,以达到最佳的性能。对于Random Access迭代器该函数传回_Last -_First的值,对于其他迭代器类型需要不断递增_First 直到抵达_Last 。、
    /****************************************************************
    *函数名称:DistanceInstance
    *功    能:distance函数应用举例
    *作    者:Jin
    *日    期:2016年5月29日
    ****************************************************************/
    void DistanceInstance()
    {
    	typedef list<int> IntList;
    	IntList Collector;
    	//insert -3 -2 -1 0 1 2 3 4 5 6 7 8 9
    	for (int i = -3; i <= 9; i++)
    	{
    		Collector.push_back(i);
    	}
    
    	//search element with value 5
    	IntList::iterator pos;
    	pos = find(Collector.begin(), Collector.end(), 5);
    	if (pos != Collector.end())
    	{
    		cout << "difference between beginning and element with value 5: "
    			 << distance(Collector.begin(), pos) << endl;
    	} 
    	else
    	{
    		cout << "can not find element with value 5" << endl;
    	}
    
    }

    Iter_swap ()

    该函数是用来交换两个迭代器所指的元素值,函数原型如下:
    void iter_swap(_FwdIt1 pos1, _FwdIt2 pos2);
    1.迭代器的型别可以不同,但是其所指的两个值必须是可交换的。
    /****************************************************************
    *函数名称:IterSwapInstance
    *功    能:iter_swap()函数应用示例
    *作    者:Jin
    *日    期:2016年5月29日
    ****************************************************************/
    void IterSwapInstance()
    {
    
    	typedef vector<int> IntVector;
    	IntVector coll;
    	for (int i = 1; i <= 9; ++i)
    	{
    		coll.push_back(i);
    	}
    	
    	//output:1 2 3 4 5 6 7 8 9
    	PrintElements(coll,"list1:");
    
    	//output:2 1 3 4 5 6 7 8 9 
    	iter_swap(coll.begin(), ++coll.begin());
    	PrintElements(coll, "list2:");
    	
    	//output:9 1 3 4 5 6 7 8 2 
    	iter_swap(coll.begin(), --coll.end());
    	PrintElements(coll, "list3:");
    }

    迭代器特性

    在distance()函数,advance()函数中均提到,这个两个函数能根据迭代器类型采用最佳的实作方案,以达到最加的性能要求。其实现原理:通过迭代器标志(tags)和特性(traits, 由<iterator>提供),将操作行为重载得以实现。

    STL为每一种迭代器提供了一个迭代器标志(iterator tag),用来作为迭代器的标签(label):
    namespace std 
    {
    	struct output_iterator_tag 
    	{
    
    	};
    	struct input_iterator_tag
    	{
    
    	};
    
    	struct forward_iterator_tag : public input_iterator_tag
    	{
    
    	};
    
    	struct bidirectional_iterator_tag : public forward_iterator_tag
    	{
    
    	};
    	struct random_access_iterator_tag : public bidirectional_iterator_tag
    	{
    
    	};
    }
    如果编写泛型程序代码,我们还需要了解迭代器所指元素的型别。STL提供了一种特殊的template结构来定义迭代器特性(iterator traits),该结构包含了迭代器相关的所有信息,为“迭代器应具备的所有型别定义(包括迭代器类型,元素型别等)”提供一致接口:
    namespace std
    {
    	template <class T>
    	struct iterator_traits 
    	{
    		//定义迭代器所指的元素类型
    		typedef typename T::value_type value_type;
    		//定义两个迭代器距离
    		typedef typename T::difference_type difference_type;
    		//定义迭代器类型
    		typedef typename T::iterator_category iterator_category;
    		//定义指针
    		typedef typename T::pointer pointer;
    		//定义引用
    		typedef typename T::reference reference;
    	};
    }
    在这个template中,T代表迭代器型别,有了它,就可以编写任何运用“迭代器类型”等特征的泛型程序代码了,例如:
    typedef vector<int> IntVector;
    IntVector coll;
    for (int i = 1; i <= 9; ++i)
    {
    	coll.push_back(i);
    }
    iterator_traits<IntVector::iterator>::value_type temp(*coll.begin());
    这个“迭代器特性”结构有两个优点:
    1、能够确保每一个迭代器所提供必要的型别定义。
    2、能够针对特性的迭代器进行特化

    上述第二条,运用于”一般指针作“时有:
    namespace std
    {
    	template <class T>
    	struct iterator_traits<T*> 
    	{
    		typedef T value_type;
    		//定义距离
    		typedef ptrdiff_t difference_type;
    		//定义迭代器类型
    		typedef random_access_iterator_tag iterator_category;
    		//定义指针
    		typedef T* pointer;
    		//定义引用
    		typedef T& reference;
    	};
    }

    运用迭代器类型(iterator_categories)

    如果希望针对不同的迭代器类型采用不同的实作方案(采用函数重载技术),需要按照下面两步来进行:
    1.将迭代器类型作为template函数的附件参数。
    2.针对不同的迭代器类型实作出上述所调用的函数

    现在以迭代器辅助函数distance()为例介绍其调用过程,辅助函数advance()实现方法和distance()一样。
    template<class Iterator>
    typename std::iterator_traits<Iterator>::difference_type
    distance (Iterator pos1, Iterator pos2)
    {
    	return distance(pos1, pos2, 
    				    std::iterator_traits<Iterator>::iterator_category);
    }
    
    //distance for random access iterator
    template<class Raiterator>
    typename std::iterator_traits<Raiterator>::difference_type
    distance(Raiterator pos1, Raiterator pos2, std::random_access_iterator_tag)
    {
    	return pos2 - pos1;
    }
    
    //distance for input, forward, and bidirectional iterator
    template<class Initerator>
    typename std::iterator_traits<Initerator>::difference_type
    distance(Initerator pos1, Initerator pos2, std::input_iterator_tag)
    {
    	typename std::iterator_traits<Initerator>::difference_type d;
    	for (d = 0; pos1 != pos2; ++pos1, ++d)
    	{
    		;
    	}
    	return d;
    }

  • 相关阅读:
    bzoj2809 [Apio2012]dispatching
    bzoj2743[HEOI2012]采花
    bzoj3626[LNOI2014]LCA
    bzoj2038 [2009国家集训队]小Z的袜子(hose)——莫队
    bzoj2442[Usaco2011 Open]修剪草坪——单调队列优化
    bzoj1588[HNOI2002]营业额统计——双向链表
    洛谷1527(bzoj2738)矩阵乘法——二维树状数组+整体二分
    bzoj1503[NOI2004]郁闷的出纳员——Splay
    洛谷P2014——选课
    洛谷P1352——动规
  • 原文地址:https://www.cnblogs.com/jinxiang1224/p/8468412.html
Copyright © 2020-2023  润新知