The basic algorithm of STL (2)

/ generate and generate_n
//Fill the processing results of the functor gen on all elements in the [first, last) interval, the so-called filling
//It is the assignment operation of the element pointed to by the iterator
//Note: For user-defined types, provide operator = ()

template <class _ForwardIter, class _Generator>
void generate(_ForwardIter __first, _ForwardIter __last, _Generator __gen) {
  __STL_REQUIRES(_ForwardIter, _ForwardIterator);
  __STL_GENERATOR_CHECK(_Generator,
          typename iterator_traits<_ForwardIter>::value_type);
  for ( ; __first != __last; ++__first)//traverse the entire sequence
    *__first = __gen();
}
//Fill the processing results of the functor gen on the n elements starting from first, the so-called filling
//It is the assignment operation of the element pointed to by the iterator
template <class _OutputIter, class _Size, class _Generator>
_OutputIter generate_n(_OutputIter __first, _Size __n, _Generator __gen) {
  __STL_REQUIRES(_OutputIter, _OutputIterator);
  for ( ; __n > 0; --__n, ++__first)//limited to n elements
    *__first = __gen();
  return __first;
}
/*
The following are related algorithms for calculating set sets, namely union set_union, difference set_difference, intersection set_intersection
And symmetric difference set_symmetric_difference, this is a function that provides two versions of the function prototype
The first version uses the default sort comparison operator<
The second version is that the user specifies the sorting method by comp
Note: The input intervals accepted by these four algorithms are all ordered, and the outputs are also ordered
*/

// Set algorithms: includes, set_union, set_intersection, set_difference,
// set_symmetric_difference.  All of these algorithms have the precondition
// that their input ranges are sorted and the postcondition that their output
// ranges are sorted.

// Determine whether [first1, last1) contains [first2, last2),  
// Note: The two intervals must be in order, the default sorting method is operator<, if you want to define the sorting method yourself, call the second version;
template <class _InputIter1, class _InputIter2>
bool includes(_InputIter1 __first1, _InputIter1 __last1,
              _InputIter2 __first2, _InputIter2 __last2) {
  __STL_REQUIRES(_InputIter1, _InputIterator);
  __STL_REQUIRES(_InputIter2, _InputIterator);
  __STL_REQUIRES_SAME_TYPE(
       typename iterator_traits<_InputIter1>::value_type,
       typename iterator_traits<_InputIter2>::value_type);
  __STL_REQUIRES(typename iterator_traits<_InputIter1>::value_type,
                 _LessThanComparable);
  while (__first1 != __last1 && __first2 != __last2)//traverse two intervals
    if (*__first2 < *__first1)//first2 less than first1 means not included
      return false;//return FALSE
    else if(*__first1 < *__first2)//If first1 is less than first2
      ++__first1;//Find the next position in the first interval
    else
      ++__first1, ++__first2;//If first2 is equal to first1, traverse the next position of the two intervals

  return __first2 == __last2;//If the second interval reaches the end first, return TRUE
}

//Version 2: The user specifies the sorting method by comp
template <class _InputIter1, class _InputIter2, class _Compare>
bool includes(_InputIter1 __first1, _InputIter1 __last1,
              _InputIter2 __first2, _InputIter2 __last2, _Compare __comp) {
  __STL_REQUIRES(_InputIter1, _InputIterator);
  __STL_REQUIRES(_InputIter2, _InputIterator);
  __STL_REQUIRES_SAME_TYPE(
       typename iterator_traits<_InputIter1>::value_type,
       typename iterator_traits<_InputIter2>::value_type);
  __STL_BINARY_FUNCTION_CHECK(_Compare, bool,
       typename iterator_traits<_InputIter1>::value_type,
       typename iterator_traits<_InputIter2>::value_type);
  while (__first1 != __last1 && __first2 != __last2)
    if (__comp(*__first2, *__first1))
      return false;
    else if(__comp(*__first1, *__first2))
      ++__first1;
    else
      ++__first1, ++__first2;

  return __first2 == __last2;
}
// partition, stable_partition, and their auxiliary functions
//If the type of the iterator is forward_iterator_tag, call this function
template <class _ForwardIter, class _Predicate>
_ForwardIter __partition(_ForwardIter __first,
		         _ForwardIter __last,
			 _Predicate __pred,
			 forward_iterator_tag) {
  if (__first == __last) return __first;//If it is empty, exit directly

  while (__pred(*__first))//If the value of pred first is true
    if (++__first == __last) return __first;//Move the iterator first first, and judge whether it reaches the end last

  _ForwardIter __next = __first;//Continue to judge

  while (++__next != __last)//If the next position is still not the end
    if (__pred(*__next)) {//Continue to pred the value of next, if true
      swap(*__first, *__next);//Swap values
      ++__first;//Continue to the next position
    }

  return __first;
}
//If the type of the iterator is bidirectional_iterator_tag, call this function
template <class _BidirectionalIter, class _Predicate>
_BidirectionalIter __partition(_BidirectionalIter __first,
                               _BidirectionalIter __last,
			       _Predicate __pred,
			       bidirectional_iterator_tag) {
  while (true) {
    while (true)
      if (__first == __last)//If empty
        return __first;//Exit directly
      else if (__pred(*__first))//The value of first meets the condition of not moving, then the value is not moved
        ++__first;//Only move the iterator
      else//If the head pointer matches the move
        break; // break out of the loop
    --__last;//Tail pointer backtracking
    while (true)
      if (__first == __last)//The head pointer is equal to the tail pointer
        return __first;//The end of the operation
      else if (!__pred(*__last))//The element of the tail pointer conforms to the non-moving operation
        --__last;//To move iterator, do not move specific elements
      else//The element of the tail pointer conforms to the move operation
        break; // break out of the loop
    iter_swap(__first, __last);//The head and tail pointers exchange elements
    ++__first;//Prepare for the next loop
  }
}
//Sort the elements in the interval [first, last), put those judged as true by pred in the front of the interval, and those judged as false in the back of the interval
//This calculation may cause the element position of the element to change.
/*
算法功能:Rearranges the elements from the range [first,last), in such a way that all the elements
for which pred returns true precede all those for which it returns false.
The iterator returned points to the first element of the second group.

Algorithm prototype:
	template <class BidirectionalIterator, class UnaryPredicate>
	BidirectionalIterator partition (BidirectionalIterator first,
                                   BidirectionalIterator last, UnaryPredicate pred);
*/
template <class _ForwardIter, class _Predicate>
inline _ForwardIter partition(_ForwardIter __first,
   			      _ForwardIter __last,
			      _Predicate __pred) {
  __STL_REQUIRES(_ForwardIter, _Mutable_ForwardIterator);
  __STL_UNARY_FUNCTION_CHECK(_Predicate, bool,
        typename iterator_traits<_ForwardIter>::value_type);
  //First extract the type of the iterator first, and call different functions according to the type of the iterator
  return __partition(__first, __last, __pred, __ITERATOR_CATEGORY(__first));
}



Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324822678&siteId=291194637