VS 2010 algorithm 常见函数及技巧

1、find(_Unchecked与_Rechecked)

这个函数的作用就是在一个容器的一段迭代器范围之内查找第一个与_Val相等的迭代器。这个函数有两个模板参数,一是容器迭代器类型_InIt,二是进行比较的值得类型_Ty。下面这一段代码返回的就是一个指向vecInt中第二个元素的迭代器。

	vector<int> vecInt;
	vecInt.push_back(1);
	vecInt.push_back(2);
	vecInt.push_back(3);
	find(vecInt.begin(),vecInt.end(),2);
template<class _InIt,
	class _Ty> inline
	_InIt find(_InIt _First, _InIt _Last, const _Ty& _Val)
	{	// find first matching _Val
	_DEBUG_RANGE(_First, _Last);
	return (_Rechecked(_First,
		_Find(_Unchecked(_First), _Unchecked(_Last), _Val)));
	}

上面的_Unchecked是干嘛的呢,其实就是把迭代器参数指向的那个原生指针返回来。每一个容器都会有一个全局的_Unchecked函数,用来供外部调用。

//全局函数,调用_Vector_iterator的类成员函数
template<class _Myvec> inline
	typename _Vector_iterator<_Myvec>::_Unchecked_type
		_Unchecked(_Vector_iterator<_Myvec> _Iter)
	{	// convert to unchecked
	return (_Iter._Unchecked());
	}
_Unchecked_type _Vector_iterator::_Unchecked() const
		{	// make an unchecked iterator
        //在这里_Unchecked_type就是int*啦,毕竟我们上面示例代码vector的元素类型是int
		return (_Unchecked_type(this->_Ptr));
		}

上面一天unchecked的操作之后,调用下面这个_Find,其实stl里面带"_"下划线的命名,都代表给内部调用的。在我们这个环境下,此时_InIt代表的实际类型就是 int* 啦。

template<class _InIt,
	class _Ty> inline
	_InIt _Find(_InIt _First, _InIt _Last, const _Ty& _Val)
	{	// find first matching _Val
	for (; _First != _Last; ++_First)
		if (*_First == _Val)
			break;
	return (_First);
	}

上面这个_Find就是利用原生指针,一通查找,最后返回一个int* 。再返回到find函数,里面有一个把find函数返回的int* _Rechecked成一个iterator的操作。这里面就是利用_Rechecked的第一个迭代器参数,这是一个引用,把原始指针赋值到第一个迭代器参数的成员函数里,反正就是说此迭代器指向和_Rechecked第二个int* 参数_Right相同元素。关于容器迭代器部分内容可以参考我的关于vector源码分析的文章https://blog.csdn.net/LiQian06336/article/details/99181398

template<class _Myvec> inline
	_Vector_iterator<_Myvec>&
		_Rechecked(_Vector_iterator<_Myvec>& _Iter,
			typename _Vector_iterator<_Myvec>
				::_Unchecked_type _Right)
	{	// convert to checked
	return (_Iter._Rechecked(_Right));
	}
	_Myiter& _Rechecked(_Unchecked_type _Right)
		{	// reset from unchecked iterator
		this->_Ptr = _Right;
		return (*this);
		}

2、find_if(函数指针、仿函数、Lambda表达式)

find的第三个参数是一个 值,在容器的一段范围内找第一个和此值相等的迭代器;而find_if的第三个参数是一个函数(或者和函数具有相同功能的仿函数,Lambda表达式),找一个满足此函数的迭代器。此函数参数只有一个,类型为容器元素类型,返回值类型可以转换为bool。

template<class _InIt,
	class _Pr> inline
	_InIt find_if(_InIt _First, _InIt _Last, _Pr _Pred)
	{	// find first satisfying _Pred
	_DEBUG_RANGE(_First, _Last);
	_DEBUG_POINTER(_Pred);
	return (_Rechecked(_First,
		_Find_if(_Unchecked(_First), _Unchecked(_Last), _Pred)));
	}
template<class _InIt,
	class _Pr> inline
	_InIt _Find_if(_InIt _First, _InIt _Last, _Pr _Pred)
	{	// find first satisfying _Pred
	for (; _First != _Last; ++_First)
		if (_Pred(*_First))
			break;
	return (_First);
	}

函数指针版本

bool third_multiple(int num){
	return !(num%3);
}
void main()
{
	vector<int> vecInt;
		for (int i = 0;i<100;i++){
		vecInt.push_back(i);
	}
	find_if(vecInt.begin(),vecInt.end(),third_multiple);
}

仿函数版本

class third_multiple
{
public://供外部调用,必须是public
	bool operator ()(int num){
		return !(num%3);
	}	
};

void main()
{
	vector<int> vecInt;
		for (int i = 0;i<100;i++){
		vecInt.push_back(i);
	}
	find_if(vecInt.begin(),vecInt.end(),third_multiple());//third_multiple加括号
}

Lambda表达式版本

//具名仿函数版本
void main()
{
 	auto third_multiple = [](int num)->bool{
 		return !(num%3);
 	};
	vector<int> vecInt;
	for (int i = 0;i<100;i<i++){
		vecInt.push_back(i);
	}
	find_if(vecInt.begin(),vecInt.end(),third_multiple);
}

//隐士仿函数版本
void main()
{
	vector<int> vecInt;
	for (int i = 0;i<100;i<i++){
		vecInt.push_back(i);
	}
    //隐士仿函数直接放在find_if第三个参数位置处
	find_if(vecInt.begin(),vecInt.end(),[](int num)->bool{
		return !(num%3);
	});
}

3、transform(iterator_category 、函数适配器、ostream_iterator)

template<class _InIt,
	class _OutIt,
	class _Fn1> inline
	_OutIt transform(_InIt _First, _InIt _Last,
		_OutIt _Dest, _Fn1 _Func)
	{	// transform [_First, _Last) with _Func
	if (_First != _Last)
		return (_Transform1(_Unchecked(_First), _Unchecked(_Last),
			_Dest, _Func, _Is_checked(_Dest)));
	return (_Dest);
	}
template<class _InIt,
	class _OutIt,
	class _Fn1> inline
	_OutIt _Transform1(_InIt _First, _InIt _Last,
		_OutIt _Dest, _Fn1 _Func, _STD tr1::true_type)
	{	// transform [_First, _Last) with _Func, checked dest
	return (_Transform1(_First, _Last,
		_Dest, _Func,
		_Iter_cat(_First), _Iter_cat(_Dest)));
	}

_Iter_cat这个函数 返回 它的参数_Iter的 iterator_category 。iterator_category就是 c++ 泛型编程里的知识点。有五种:input_iterator_tag、output_iterator_tag、forward_iterator_tag、bidirectional_iterator_tag、random_access_iterator_tag。利用这些不同iterator_tag类型的变量,就可以使用c++ 函数重载原则,调用不同的函数。

template<class _Iter> inline
	typename iterator_traits<_Iter>::iterator_category
		_Iter_cat(const _Iter&)
	{	// return category from iterator argument
	typename iterator_traits<_Iter>::iterator_category _Cat;
	return (_Cat);
	}

下面这个版本,第四和第五个参数类型分别为 input_iterator_tag、output_iterator_tag,意思就是输入迭代器和输出迭代器。  当然还有重载其他参数类型的模板。

template<class _InIt,
	class _OutIt,
	class _Fn1> inline
	_OutIt _Transform1(_InIt _First, _InIt _Last,
		_OutIt _Dest, _Fn1 _Func,
		input_iterator_tag, output_iterator_tag)
	{	// transform [_First, _Last) with _Func, arbitrary iterators
	return (_Transform(_First, _Last,
		_Dest, _Func));
	}

这里就是把值赋值到输出迭代器中去,这里注意:这个输出迭代器既可以是容器迭代器,比如vector::iterator,也可以是ostream_iterator。

		// TEMPLATE FUNCTION transform WITH UNARY OP
template<class _InIt,
	class _OutIt,
	class _Fn1> inline
	_OutIt _Transform(_InIt _First, _InIt _Last,
		_OutIt _Dest, _Fn1 _Func)
	{	// transform [_First, _Last) with _Func
	for (; _First != _Last; ++_First, ++_Dest)
		*_Dest = _Func(*_First);
	return (_Dest);
	}

函数转发器 

我们transform的第四个参数_Func是一个具有函数功能的模板,_Func的参数只有一个,且类型就是元素类型。但是假如我要给输入迭代器里面的每一个元素加N,该怎么做呢。可以利用仿函数,仿函数类里有一个成员变量保存我们的另一个加数。如下代码:

class MyPlus{
public:
	MyPlus(int input){
		this->input = input;
	}
	int operator ()(int num){
		return num+input;
	}
private:
	int input;//把另一个加数保存在这里
};

void main()
{
	vector<int> my_int_vector;
	for (int i = 0;i<10;i++)
	{
		my_int_vector.push_back(i);
	}
	ostream_iterator<double,char> out(cout," ");
	MyPlus my_plus(100);
	transform(my_int_vector.begin(),my_int_vector.end(),out,my_plus);
}

假如现在有一个函数int plus_func (int,int);我想把plus_func放到我transform的第四个参数处,这样肯定会编译失败,因为,transform的第四个“函数“”参数_Func只接收一个参数,这时候就需要把plus_func转换成一个参数的函数。如下面代码。

int plus_func(int num1,int num2){
	return num1+num2;
}
//MyPlus就是一个函数转发器,或函数包装器。其实这就是 设计模式 里面的 适配器模式。
class MyPlus{
public:
	MyPlus(int input){
		this->input = input;
	}
	int operator ()(int num){
		return plus_func(num,input);
	}
private:
	int input;
};

ostream_iterator 

transform的第三个参数可以是一个output迭代器,比如这个迭代器可以是,我们定义的一个容器的begin(),那么我们把输入迭代器范围内的值经过第四个参数一通处理之后放到此output容器中。我们示例代码中,却是把计算后的值,放到ostream_iterator中,即把计算出来的值一一打印出来。ostream_iterator 的实现精髓就是,在重载的赋值构造函数中,每把一个元素赋值给此迭代器,就把此元素打印出来。

template<class _Ty,
	class _Elem = char,
	class _Traits = char_traits<_Elem> >
	class ostream_iterator
		: public _Outit
	{	// wrap _Ty inserts to output stream as output iterator
public:
	typedef _Elem char_type;
	typedef _Traits traits_type;
	typedef basic_ostream<_Elem, _Traits> ostream_type;
    //构造函数 _Ostr我们示例中传的 是cout,
	ostream_iterator(ostream_type& _Ostr,_Delim,即分隔字符串,我们传的是" "
		const _Elem *_Delim = 0)
		: _Myostr(&_Ostr), _Mydelim(_Delim)
		{	// construct from output stream and delimiter
		}
    //赋值构造函数,每把一个_Val传进来,我们就把他用cout打印出来
	ostream_iterator<_Ty, _Elem, _Traits>& operator=(const _Ty& _Val)
		{	// insert value into output stream, followed by delimiter
		*_Myostr << _Val;
		if (_Mydelim != 0)
			*_Myostr << _Mydelim;//打印分隔字符串
		return (*this);
		}

	ostream_iterator<_Ty, _Elem, _Traits>& operator*()
		{	// pretend to return designated value
		return (*this);
		}
    //对于vector的迭代器,++当然是指向下一个元素,但是我们这里是打印,无所谓++了,所以只是返回本身
	ostream_iterator<_Ty, _Elem, _Traits>& operator++()
		{	// pretend to preincrement
		return (*this);
		}

	ostream_iterator<_Ty, _Elem, _Traits> operator++(int)
		{	// pretend to postincrement
		return (*this);
		}

protected:
	const _Elem *_Mydelim;	// pointer to delimiter string (NB: not freed)
	ostream_type *_Myostr;	// pointer to output stream
	};

bind1st、bind2nd 

template<class _Fn2,
	class _Ty> inline
	binder1st<_Fn2> bind1st(const _Fn2& _Func, const _Ty& _Left)
		{	// return a binder1st functor adapter
		typename _Fn2::first_argument_type _Val(_Left);
		return (_STD binder1st<_Fn2>(_Func, _Val));
		}

 bind1st是一个函数,返回一个binder1st,binder1st是一个模板,它的作用相当于我自己写的MyPlus类的作用,就是把两个参数的函数转换成一个参数的仿函数,另一个参数放到成员变量里。

template<class _Fn2>
	class binder1st
		: public unary_function<typename _Fn2::second_argument_type,
			typename _Fn2::result_type>
	{	// functor adapter _Func(stored, right)//这里英文说的很清楚,我乃函数适配器
public:
	typedef unary_function<typename _Fn2::second_argument_type,
		typename _Fn2::result_type> _Base;
	typedef typename _Base::argument_type argument_type;
	typedef typename _Base::result_type result_type;
    //构造函数,很简单,就是把要封装的二元参数函数_Func和_Func的第一个参数传进来
	binder1st(const _Fn2& _Func,
		const typename _Fn2::first_argument_type& _Left)
		: op(_Func), value(_Left)
		{	// construct from functor and left operand
		}
    //重载(),即仿函数的函数调用部分,里面把成员变量value放在op的第一个参数处。
	result_type operator()(const argument_type& _Right) const
		{	// apply functor to operands
		return (op(value, _Right));
		}

	result_type operator()(argument_type& _Right) const
		{	// apply functor to operands
		return (op(value, _Right));
		}

protected:
	_Fn2 op;	// the functor to apply
    //first_argument_type就是std::plus模板参数类型,这里面用到了binary_function类
	typename _Fn2::first_argument_type value;	// the left operand
	};

看看我们的例子,其实和自己写的MyPlus一个道理,只不过要用stl里面的std::plus,因为std::plus的基类里面有几个typedef,typedef定义的东西在binder1st里面作类型使用。所以要定义我们自己的plus类,也需要从binary_function继承而来。

//二元参数反函数类的基类
template<class _Arg1,
	class _Arg2,
	class _Result>
	struct binary_function
	{	// base class for binary functions
	typedef _Arg1 first_argument_type;//第一个参数类型
	typedef _Arg2 second_argument_type;//第二个参数类型
	typedef _Result result_type;//返回值参数类型
	};
template<class _Ty>
	struct plus
		: public binary_function<_Ty, _Ty, _Ty>//在“+”里,两个加数,以及和类型一致
	{	// functor for operator+
	_Ty operator()(const _Ty& _Left, const _Ty& _Right) const
		{	// apply operator+ to operands
		return (_Left + _Right);
		}
	};
void main()
{
	vector<int> my_int_vector;
	for (int i = 0;i<10;i++)
	{
		my_int_vector.push_back(i);
	}
	ostream_iterator<double,char> out(cout," ");
    //下面这个玩意儿是stl里面的,叫做“预定义的函数符”,可以查看《C++Primer+Plus第五版》16.5.2节内容
	std::plus<int> my_plus;	
	binder1st<std::plus<int> > my_binder = bind1st(my_plus,100);
	transform(my_int_vector.begin(),my_int_vector.end(),out,my_binder);
}

bind2nd和bind1st的唯一不同,就是把绑定的那个成员变量,放到绑定函数的第二个参数处,仅此而已。 

4、remove_if

template<class _FwdIt,
	class _Pr> inline
	_FwdIt remove_if(_FwdIt _First, _FwdIt _Last, _Pr _Pred)
	{	// remove each satisfying _Pred
	_First = _STD find_if(_First, _Last, _Pred);
	if (_First == _Last)
		return (_First);	// empty sequence, all done
	else
		return (_Rechecked(_First,
			_Remove_if(_Unchecked(_First), _Unchecked(_Last), _Pred)));
	}
template<class _FwdIt,
	class _Pr> inline
	_FwdIt _Remove_if(_FwdIt _First, _FwdIt _Last, _Pr _Pred)
	{	// remove each satisfying _Pred
	_FwdIt _Next = _First;
	for (++_First; _First != _Last; ++_First)
	if (!_Pred(*_First))
		*_Next++ = _Move(*_First);
	return (_Next);
	}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值