STL复习之算法二

  1、search(s1,e1,s2,e2)。在序列[s1,e1)内寻找序列[s2,e2)第一次出现的位置,若后者并不在前者的区间内,则返回前者区间的末尾,即e1。

函数原型:

  template<typename _ForwardIterator1, typename _ForwardIterator2,
	   typename _BinaryPredicate>
    _ForwardIterator1
    __search(_ForwardIterator1 __first1, _ForwardIterator1 __last1,
	     _ForwardIterator2 __first2, _ForwardIterator2 __last2,
	     _BinaryPredicate  __predicate)

实现:

  template<typename _ForwardIterator1, typename _ForwardIterator2,
	   typename _BinaryPredicate>
  template<typename _ForwardIterator1, typename _ForwardIterator2,
	   typename _BinaryPredicate>
    _ForwardIterator1
    __find_end(_ForwardIterator1 __first1, _ForwardIterator1 __last1,
	       _ForwardIterator2 __first2, _ForwardIterator2 __last2,
	       forward_iterator_tag, forward_iterator_tag,
	       _BinaryPredicate __comp)
    {
      if (__first2 == __last2)
	return __last1;

      _ForwardIterator1 __result = __last1;
      while (1)
	{
	  _ForwardIterator1 __new_result
	    = std::__search(__first1, __last1, __first2, __last2, __comp);
	  if (__new_result == __last1)
	    return __result;
	  else
	    {
	      __result = __new_result;
	      __first1 = __new_result;
	      ++__first1;
	    }
	}
    }


_ForwardIterator1 __search(_ForwardIterator1 __first1, _ForwardIterator1 __last1, _ForwardIterator2 __first2, _ForwardIterator2 __last2, _BinaryPredicate __predicate) { //找与被找序列的任意一个为空,就无法找到被找的序列,返回__first1 if (__first1 == __last1 || __first2 == __last2)return __first1; // __p1指向要找的序列的第一个元素 _ForwardIterator2 __p1(__first2); if (++__p1 == __last2) //要找的序列只有一个元素,直接调用find_if返回结果return std::__find_if(__first1, __last1,__gnu_cxx::__ops::__iter_comp_iter(__predicate, __first2)); // 函数走到这里,说明要找的序列至少有两个元素且上面的迭代器__p1已经指向了要找的序列的第二个元素 _ForwardIterator2 __p; _ForwardIterator1 __current = __first1;//__current指向被找序列的第一个元素 for (;;){ //在区间[__first1,__last1)内找__first2第一次出现的位置,并将结果保存在__first1中 __first1 = std::__find_if(__first1, __last1,__gnu_cxx::__ops::__iter_comp_iter(__predicate, __first2)); //第一个元素就找不到,结束寻找 if (__first1 == __last1) return __last1; //p1指向了要找的序列的第二个元素,因此__p也指向了要找的序列的第二个元素,__current指向要找的序列的第一个元素在当前被找序列中时首次出现的位置 __p = __p1; __current = __first1; if (++__current == __last1) //要找的序列的第一个元素的位置在被找序列的最后一个元素的位置处,因此,要找的序列只能在被找的序列中找到一个元素, return __last1; //而要找的序列的元素个数大于1,因此,要找的序列肯定找不到,直接返回__last1 while (__predicate(__current, __p))//执行到while循环,__current指向被找序列的第二个元素,__p指向要找的序列的第二个元素 { if (++__p == __last2) //要找的序列已经找完,则说明查找成功,返回这个序列在被找的序列中首次出现的位置return __first1; if (++__current == __last1)//要找的序列还未走完,而被找的序列已经走完,注定找不到,直接返回return __last1; //否则,__p与__current均前进一个单位 } ++__first1; /缩小被找的序列的范围     } return __first1; //不知为何 }2、find_end(s1,e1,s2,e2)。在序列[s1,e1)内找[s2,e2)序列,返回后者在前者中最后一次出现的位置,若找不到,则返回e1。

函数原型:

  template<typename _ForwardIterator1, typename _ForwardIterator2,
	   typename _BinaryPredicate>
    _ForwardIterator1
    __find_end(_ForwardIterator1 __first1, _ForwardIterator1 __last1,
	       _ForwardIterator2 __first2, _ForwardIterator2 __last2,
	       forward_iterator_tag, forward_iterator_tag,
	       _BinaryPredicate __comp)

算法实现:

  template<typename _ForwardIterator1, typename _ForwardIterator2,
	   typename _BinaryPredicate>
    _ForwardIterator1
    __find_end(_ForwardIterator1 __first1, _ForwardIterator1 __last1,
	       _ForwardIterator2 __first2, _ForwardIterator2 __last2,
	       forward_iterator_tag, forward_iterator_tag,
	       _BinaryPredicate __comp)
    {
      if (__first2 == __last2) //要找的序列为空,就意味着找不到,直接结束算法运行,返回__last1
	return __last1;

      _ForwardIterator1 __result = __last1;
      while (1)
	{
	  _ForwardIterator1 __new_result
	    = std::__search(__first1, __last1, __first2, __last2, __comp);//在当前的序列区间[__first1,__last1)
	  if (__new_result == __last1)                                    //找序列[__first2,__last2)首次出现的位置,找不到,直接结束算法
	    return __result;
	  else
	    {
	      __result = __new_result; //__result纪录最近一次成功找到要找的序列在被找序列中首次出现的位置
	      __first1 = __new_result; //以下两步是为了缩小被找的区间
	      ++__first1;
	    }
	}
    }

3、bool includes(s1,e1,s2,e2)。检查序列区间[s1,e1)是否包含序列区间[s2,e2),若包含则返回为true,否则返回为false。注意到序列区间[s2,e2)在序列区间[s1,e1)内不一定要连续。并且要尤其注意的是,这个算法的前置条件要求序列区间[s1,e1)与序列区间[s2,e2)中的元素必须有序(sorted)。

函数原型:

  template<typename _InputIterator1, typename _InputIterator2,
	   typename _Compare>
    bool
    __includes(_InputIterator1 __first1, _InputIterator1 __last1,
	       _InputIterator2 __first2, _InputIterator2 __last2,
	       _Compare __comp)

函数实现:

  template<typename _InputIterator1, typename _InputIterator2,
	   typename _Compare>
    bool
    __includes(_InputIterator1 __first1, _InputIterator1 __last1,
	       _InputIterator2 __first2, _InputIterator2 __last2,
	       _Compare __comp)
    {
      while (__first1 != __last1 && __first2 != __last2) //两个序列区间均未走完
	if (__comp(__first2, __first1)) //要找的序列区间中存在元素在被找区间中不存在,直接结束算法
	  return false;
	else if (__comp(__first1, __first2))被找的区间中存在着元素而要找的区间中并不存在,被找区间跳过当前元素
	  ++__first1;
	else
	  ++__first1, ++__first2;//要找的区间中的当前元素在被找区间中存在,两个区间中的迭代器均前进一

      return __first2 == __last2;//最后检查要找的区间中的元素是否已经找完
    }

4、merge(s1,e1,s2,e2)。合并两个有序序列[s1,e1)与[s2,e2)为一个。注意到到被合并的两个序列必须是有序的且同一元素既可以在序列[s1,e1)中出现,也可以在序列[s2,e2)中出现,记某个元素在前者序列中出现的次数为m,在后者序列中出现的次数为n,则其在合并后的序列中出现的次数为m+n。

函数原型:

  template<typename _InputIterator1, typename _InputIterator2,
	   typename _OutputIterator, typename _Compare>
    _OutputIterator
    __merge(_InputIterator1 __first1, _InputIterator1 __last1,
	    _InputIterator2 __first2, _InputIterator2 __last2,
	    _OutputIterator __result, _Compare __comp)

[__first1,__last1)与[__first2,__last2)表示两个序列区间,__result为指向即将要准备合并的区间的迭代器,__comp表示两个区间中的元素进行比较的二元运算符。

算法实现:

  template<typename _InputIterator1, typename _InputIterator2,
	   typename _OutputIterator, typename _Compare>
    _OutputIterator
    __merge(_InputIterator1 __first1, _InputIterator1 __last1,
	    _InputIterator2 __first2, _InputIterator2 __last2,
	    _OutputIterator __result, _Compare __comp)
    {
      while (__first1 != __last1 && __first2 != __last2 //准备进行合并的两个区间均为走完
	{
	  if (__comp(__first2, __first1))//__comp(__first2,__first1)为true,将__first2指向的元素纪录下来,并将迭代器__first2前进一
	    {
	      *__result = *__first2;
	      ++__first2;
	    }
	  else                          //__comp(__first2,__first1)为false,将__first1指向的元素纪录下来,并将迭代器__first1前进一
	    {
	      *__result = *__first1;
	      ++__first1;
	    }
	  ++__result;//纪录结果的迭代器往后移动一个单位
	}
      return std::copy(__first2, __last2,
		       std::copy(__first1, __last1, __result));//未遍历完的区间copy至结果集末尾。
    }

测试代码:

#include <algorithm>
#include <vector>
#include <iostream>
#include <iostream>
void printEle(std::vector<int>& intArray)
{
  for(int i=0;i<intArray.size();++i)
    std::cout<<intArray[i]<<"\t";

  std::cout<<std::endl;
}

int main(int argc, char *argv[])
{
  std::vector<int> intArrayA={1,2,2,3,3,4,5,6,6,7,8,9};
  std::vector<int> intArrayB={1,1,1,2,3,4,4,5,7,8};
  std::vector<int> resultArray;
  resultArray.resize(intArrayA.size()+intArrayB.size());

  std::cout<<"before merge: A\n";
  printEle(intArrayA);
  std::cout<<"before merge: B\n";
  printEle(intArrayB);

  std::merge(intArrayA.begin(),intArrayA.end(),intArrayB.begin(),intArrayB.end(),resultArray.begin());

  std::cout<<"after merge:\n";
  printEle(resultArray);
  return 0;
}

测试结果:

猜你喜欢

转载自blog.csdn.net/weixin_40825228/article/details/81060135