STL算法_基本算法篇
1)equal算法:用来比较两个序列在[first,last)区间内是否相等。如果第二个序列的元素多于第一个序列元素,则多出的元素不予考虑。
// equal算法用来判断两个序列在[frist,last)区间内是否相等。当第二个序列的元素较多时,多出来的元素不予考虑。 // 版本1 template inline bool equal(_inputiter1 __first1, _inputiter1 __last1, _inputiter2 __first2) { __stl_requires(_inputiter1, _inputiterator); __stl_requires(_inputiter2, _inputiterator); __stl_requires(typename iterator_traits<_inputiter1>::value_type, _equalitycomparable); __stl_requires(typename iterator_traits<_inputiter2>::value_type, _equalitycomparable); // 以下,将序列一走过一遍。序列二亦步亦趋 // 如果序列一的元素个数多序列二的个数,就糟糕了 for ( ; __first1 != __last1; ++__first1, ++__first2) if (*__first1 != *__first2) // 只要对应元素不相等 return false; // 就结束并返回false return true; // 至此,全部相等,返回true } // 版本2 template inline bool equal(_inputiter1 __first1, _inputiter1 __last1, _inputiter2 __first2, _binarypredicate __binary_pred) { __stl_requires(_inputiter1, _inputiterator); __stl_requires(_inputiter2, _inputiterator); for ( ; __first1 != __last1; ++__first1, ++__first2) if (!__binary_pred(*__first1, *__first2)) return false; return true; }
2)fill算法:将[first,last)内的所有元素改填新值。
// fill算法用来将[first,last)内的所有元素改填新值 template void fill(_forwarditer __first, _forwarditer __last, const _tp& __value) { __stl_requires(_forwarditer, _mutable_forwarditerator); for ( ; __first != __last; ++__first) // 迭代走过整个区间 *__first = __value; // 设定新值 } // 版本2 // 特例化,针对单字节类型使用memset函数实现 inline void fill(unsigned char* __first, unsigned char* __last, const unsigned char& __c) { unsigned char __tmp = __c; memset(__first, __tmp, __last - __first); } inline void fill(signed char* __first, signed char* __last, const signed char& __c) { signed char __tmp = __c; memset(__first, static_cast(__tmp), __last - __first); } inline void fill(char* __first, char* __last, const char& __c) { char __tmp = __c; memset(__first, static_cast(__tmp), __last - __first); }
3)fill_n算法:将[first,last)内的前n个元素改填新值,返回的迭代器指向被填入的最后一个元素的下一个位置。
// fill_n算法用来将[first,last)内的前n个元素改填新值,返回的迭代器指向被填入的最后一个元素的下一位置 template _outputiter fill_n(_outputiter __first, _size __n, const _tp& __value) { __stl_requires(_outputiter, _outputiterator); for ( ; __n > 0; --__n, ++__first) // 经过n个元素 *__first = __value; // 设定新值 return __first; } // 版本2 #ifdef __stl_function_tmpl_partial_order template inline unsigned char* fill_n(unsigned char* __first, _size __n, const unsigned char& __c) { fill(__first, __first + __n, __c); return __first + __n; } template inline signed char* fill_n(char* __first, _size __n, const signed char& __c) { fill(__first, __first + __n, __c); return __first + __n; } template inline char* fill_n(char* __first, _size __n, const char& __c) { fill(__first, __first + __n, __c); return __first + __n; }
4)iter_swap算法:将两个forwarditerator所指对象对调。它是迭代器value type派上用场的一个好例子。该函数必须知道迭代器的value type,才能够据此声明一个对象,用来暂时存放迭代器所指对象。
// iter_swap算法:将两个forwarditerator所指对象对调。它是迭代器value type派上用场的一个好例子。 // 该函数必须知道迭代器的value type,才能够据此声明一个对象,用来暂时存放迭代器所指对象。 template inline void __iter_swap(_forwarditer1 __a, _forwarditer2 __b, _tp*) { _tp __tmp = *__a; // 执行交换过程 *__a = *__b; *__b = __tmp; } // iter_swap算法用来将两个forwarditerator所指对象对调。它是迭代器值value type派上用场的一个好例子。 template inline void iter_swap(_forwarditer1 __a, _forwarditer2 __b) { __stl_requires(_forwarditer1, _mutable_forwarditerator); __stl_requires(_forwarditer2, _mutable_forwarditerator); __stl_convertible(typename iterator_traits<_forwarditer1>::value_type, typename iterator_traits<_forwarditer2>::value_type); __stl_convertible(typename iterator_traits<_forwarditer2>::value_type, typename iterator_traits<_forwarditer1>::value_type); __iter_swap(__a, __b, __value_type(__a)); }
5)lexicographical_compare算法:以“字典排列方式”对两个序列[first1,last1)和[firs2,last2)进行比较。比较操作针对两序列中的对应位置上的元素进行,并持续直到1)某一组对应元素彼此不相等;2)同时到达last1和last2(当两序列的大小相同);3)到达last1或last2(当两序列的大小不同)。
这两个函数在对应位置上发现第一组不相等的元素时,有以下几种可能:1)如果第一序列的元素较小,返回true,否则返回false;2)如果到达last1而尚未到达last2,返回true;3)如果达到last2而尚未到达last1,返回false;4)如果同时到达last1和last2(即所有元素都匹配)返回false。
// lexicographical_compare算法用来以“字典排列方式”对两个序列[first1,last1)和[firs2,last2)进行比较。 // 版本1 template bool lexicographical_compare(_inputiter1 __first1, _inputiter1 __last1, _inputiter2 __first2, _inputiter2 __last2) { __stl_requires(_inputiter1, _inputiterator); __stl_requires(_inputiter2, _inputiterator); __stl_requires(typename iterator_traits<_inputiter1>::value_type, _lessthancomparable); __stl_requires(typename iterator_traits<_inputiter2>::value_type, _lessthancomparable); // 以下,任何一个序列到达尾端,就结束。否则两序列就相应元素意义进行比较 for ( ; __first1 != __last1 && __first2 != __last2 ; ++__first1, ++__first2) { if (*__first1 < *__first2) // 第一序列元素值小于第二序列的相应元素值 return true; if (*__first2 < *__first1) // 第二序列元素值小于第一序列的相应元素值 return false; // 如果不符合以上两条件,表示两值相等,那就进行下一组相应元素值的比对 } // 进行到这里,如果第一序列到达尾端而第二序列尚有余额,那么第一序列小于第二序列 return __first1 == __last1 && __first2 != __last2; } // 版本2 template bool lexicographical_compare(_inputiter1 __first1, _inputiter1 __last1, _inputiter2 __first2, _inputiter2 __last2, _compare __comp) { __stl_requires(_inputiter1, _inputiterator); __stl_requires(_inputiter2, _inputiterator); for ( ; __first1 != __last1 && __first2 != __last2 ; ++__first1, ++__first2) { if (__comp(*__first1, *__first2)) return true; if (__comp(*__first2, *__first1)) return false; } return __first1 == __last1 && __first2 != __last2; } // lexicograhical_compare算法用来以“字典排列方式”对两个序列[first1,last1)和[firs2,last2)进行比较。 // 下面利用原生指针const unsigned char *实现 // 版本3 inline bool lexicographical_compare(const unsigned char* __first1, const unsigned char* __last1, const unsigned char* __first2, const unsigned char* __last2) { const size_t __len1 = __last1 - __first1; // 第一序列长度 const size_t __len2 = __last2 - __first2; // 第二序列长度 const int __result = memcmp(__first1, __first2, min(__len1, __len2)); // 先比较相同长度的一段。memcmp()速度极快 return __result != 0 ? __result < 0 : __len1 < __len2; // 如果不相上下,则长度较长者被视为比较大 } // 版本4 inline bool lexicographical_compare(const char* __first1, const char* __last1, const char* __first2, const char* __last2) { #if char_max == schar_max return lexicographical_compare((const signed char*) __first1, (const signed char*) __last1, (const signed char*) __first2, (const signed char*) __last2); #else /* char_max == schar_max */ return lexicographical_compare((const unsigned char*) __first1, (const unsigned char*) __last1, (const unsigned char*) __first2, (const unsigned char*) __last2); #endif /* char_max == schar_max */ }
6)max算法:取两个对象中的较大值。
// max算法用来取两个对象中的较大值 // 版本1 template inline const _tp& max(const _tp& __a, const _tp& __b) { __stl_requires(_tp, _lessthancomparable); return __a < __b ? __b : __a; } // 版本2 template inline const _tp& max(const _tp& __a, const _tp& __b, _compare __comp) { return __comp(__a, __b) ? __b : __a; // 有comp决定“大小比较”标准 }
7)min算法:取两个对象中的较小值。
// min算法用来取两个对象中的较小值 // 版本1 template inline const _tp& min(const _tp& __a, const _tp& __b) { __stl_requires(_tp, _lessthancomparable); return __b < __a ? __b : __a; } // 版本2 template inline const _tp& min(const _tp& __a, const _tp& __b, _compare __comp) { return __comp(__b, __a) ? __b : __a; }
8)mismatch算法:用来平行比较两个序列,指出两者之间的第一个不匹配点。返回一对迭代器,分别指向两序列中的不匹配点。如果两序列的所有对应元素都匹配,返回的便是两序列各自的last迭代器。如果第二序列的元素个数比第一序列多,多出来的元素忽略不计。如果第二序列的元素个数比第一序列少,会发生未可预测的行为。
// mismath算法用来平行比较两个序列,指出两者之间的第一个不匹配点。返回一对迭代器,分别指向两序列中的不匹配点。 // 版本1 template pair<_inputiter1, _inputiter2> mismatch(_inputiter1 __first1, _inputiter1 __last1, _inputiter2 __first2) { __stl_requires(_inputiter1, _inputiterator); __stl_requires(_inputiter2, _inputiterator); __stl_requires(typename iterator_traits<_inputiter1>::value_type, _equalitycomparable); __stl_requires(typename iterator_traits<_inputiter2>::value_type, _equalitycomparable); // 以下,如果序列一走完,就结束 // 以下,如果序列一和序列二的对应元素相等,就结束 // 显然,序列一的元素个数必须多过序列二的元素个数,否则结果无可预期 while (__first1 != __last1 && *__first1 == *__first2) { ++__first1; ++__first2; } return pair<_inputiter1, _inputiter2>(__first1, __first2); } // 版本2 template pair<_inputiter1, _inputiter2> mismatch(_inputiter1 __first1, _inputiter1 __last1, _inputiter2 __first2, _binarypredicate __binary_pred) { __stl_requires(_inputiter1, _inputiterator); __stl_requires(_inputiter2, _inputiterator); while (__first1 != __last1 && __binary_pred(*__first1, *__first2)) { ++__first1; ++__first2; } return pair<_inputiter1, _inputiter2>(__first1, __first2); }
9)swap算法:用来交换(对调)两个对象的内容。
// swap算法用来交换(对调)两个对象的内容 template inline void swap(_tp& __a, _tp& __b) { __stl_requires(_tp, _assignable); _tp __tmp = __a; // 执行交换过程 __a = __b; __b = __tmp; }
10)copy算法:将输入区间[first,last)内的元素赋值到输出区间[result,result+(last-first))内。它返回一个迭代器:result+(last-first)。copy对其template参数所要求的条件非常宽松。其输入区间只需有input构成,输出区间只需由outputiterator构成即可。copy算法,将任何容器的任何一段区间的内容,复制到任何容器的任何一段区间上。copy算法为了提高效率,使用了各种方法,包括:函数重载、型别特性、偏特化等技巧。
// copy算法用来将[first,last)内的元素复制到输出区间[result,result+(last-first))内 // inputiterator版本 template inline _outputiter __copy(_inputiter __first, _inputiter __last, _outputiter __result, input_iterator_tag, _distance*) { for ( ; __first != __last; ++__result, ++__first) // 以迭代器等同与否,决定循环是否继续。速度慢 *__result = *__first; return __result; } // randomaccessiterator版本 template inline _outputiter __copy(_randomaccessiter __first, _randomaccessiter __last, _outputiter __result, random_access_iterator_tag, _distance*) { for (_distance __n = __last - __first; __n > 0; --__n) { // 以n决定循环的次数。速度快 *__result = *__first; ++__first; ++__result; } return __result; } // 以下版本适用于“指针所指对象具备trival assignment operator” template inline _tp* __copy_trivial(const _tp* __first, const _tp* __last, _tp* __result) { memmove(__result, __first, sizeof(_tp) * (__last - __first)); return __result + (__last - __first); } #if defined(__stl_function_tmpl_partial_order) template inline _outputiter __copy_aux2(_inputiter __first, _inputiter __last, _outputiter __result, __false_type) { return __copy(__first, __last, __result, __iterator_category(__first), __distance_type(__first)); } template inline _outputiter __copy_aux2(_inputiter __first, _inputiter __last, _outputiter __result, __true_type) { return __copy(__first, __last, __result, __iterator_category(__first), __distance_type(__first)); } #ifndef __uslc__ template inline _tp* __copy_aux2(_tp* __first, _tp* __last, _tp* __result, __true_type) { return __copy_trivial(__first, __last, __result); } #endif /* __uslc__ */ template inline _tp* __copy_aux2(const _tp* __first, const _tp* __last, _tp* __result, __true_type) { return __copy_trivial(__first, __last, __result); } template inline _outputiter __copy_aux(_inputiter __first, _inputiter __last, _outputiter __result, _tp*) { typedef typename __type_traits<_tp>::has_trivial_assignment_operator _trivial; return __copy_aux2(__first, __last, __result, _trivial()); } template inline _outputiter copy(_inputiter __first, _inputiter __last, _outputiter __result) { __stl_requires(_inputiter, _inputiterator); __stl_requires(_outputiter, _outputiterator); return __copy_aux(__first, __last, __result, __value_type(__first)); } // hack for compilers that don't have partial ordering of function templates // but do have partial specialization of class templates. #elif defined(__stl_class_partial_specialization) // 完全泛化版本 template struct __copy_dispatch { static _outputiter copy(_inputiter __first, _inputiter __last, _outputiter __result) { typedef typename iterator_traits<_inputiter>::iterator_category _category; typedef typename iterator_traits<_inputiter>::difference_type _distance; return __copy(__first, __last, __result, _category(), (_distance*) 0); } }; // copy函数的泛化版本中调用一个__copy_dispatch()函数,此函数有一个完全泛化版本和两个偏特化版本 // 偏特化版本(1),两个参数都是t*指针形式 template struct __copy_dispatch<_tp*, _tp*, __true_type> { static _tp* copy(const _tp* __first, const _tp* __last, _tp* __result) { return __copy_trivial(__first, __last, __result); } }; // 偏特化版本(2),第一个参数为const t*指针形式,第二个参数为t*指针形式 template struct __copy_dispatch { static _tp* copy(const _tp* __first, const _tp* __last, _tp* __result) { return __copy_trivial(__first, __last, __result); } }; // 完全泛化版本 template inline _outputiter copy(_inputiter __first, _inputiter __last, _outputiter __result) { __stl_requires(_inputiter, _inputiterator); __stl_requires(_outputiter, _outputiterator); typedef typename iterator_traits<_inputiter>::value_type _tp; typedef typename __type_traits<_tp>::has_trivial_assignment_operator _trivial; return __copy_dispatch<_inputiter, _outputiter, _trivial> ::copy(__first, __last, __result); } // fallback for compilers with neither partial ordering nor partial // specialization. define the faster version for the basic builtin // types. #else /* __stl_class_partial_specialization */ template inline _outputiter copy(_inputiter __first, _inputiter __last, _outputiter __result) { return __copy(__first, __last, __result, __iterator_category(__first), __distance_type(__first)); } #define __sgi_stl_declare_copy_trivial(_tp) \ inline _tp* copy(const _tp* __first, const _tp* __last, _tp* __result) { \ memmove(__result, __first, sizeof(_tp) * (__last - __first)); \ return __result + (__last - __first); \ } __sgi_stl_declare_copy_trivial(char) __sgi_stl_declare_copy_trivial(signed char) __sgi_stl_declare_copy_trivial(unsigned char) __sgi_stl_declare_copy_trivial(short) __sgi_stl_declare_copy_trivial(unsigned short) __sgi_stl_declare_copy_trivial(int) __sgi_stl_declare_copy_trivial(unsigned int) __sgi_stl_declare_copy_trivial(long) __sgi_stl_declare_copy_trivial(unsigned long) #ifdef __stl_has_wchar_t __sgi_stl_declare_copy_trivial(wchar_t) #endif #ifdef _stl_long_long __sgi_stl_declare_copy_trivial(long long) __sgi_stl_declare_copy_trivial(unsigned long long) #endif __sgi_stl_declare_copy_trivial(float) __sgi_stl_declare_copy_trivial(double) __sgi_stl_declare_copy_trivial(long double) #undef __sgi_stl_declare_copy_trivial #endif
11)copy_backward算法:将[first,last)区间内的每一个元素,以逆性的方向复制到以result-1为起点,方向亦为逆行的区间上。返回一个迭代器:result-(last-first)。copy_backward所接受的迭代器必须是bidirectionaliterators,才能够“倒行逆施”。使用copy_backward算法,可将任何容器的任何一段区间的内容,复制到任何容器的任何一段区间上。如果输入区间和输出区间完全没有重叠,则毫无问题,否则需特别注意。
// copy_backward算法用来将[first,last)区间内的每一个元素,以逆行的方向复制到以result-1为起点,方向亦为逆行的区间上。 // bidirectionaliter版本 template inline _bidirectionaliter2 __copy_backward(_bidirectionaliter1 __first, _bidirectionaliter1 __last, _bidirectionaliter2 __result, bidirectional_iterator_tag, _distance*) { while (__first != __last) *--__result = *--__last; return __result; } // randomaccessiter班本 template inline _bidirectionaliter __copy_backward(_randomaccessiter __first, _randomaccessiter __last, _bidirectionaliter __result, random_access_iterator_tag, _distance*) { for (_distance __n = __last - __first; __n > 0; --__n) *--__result = *--__last; return __result; } #ifdef __stl_class_partial_specialization // this dispatch class is a workaround for compilers that do not // have partial ordering of function templates. all we're doing is // creating a specialization so that we can turn a call to copy_backward // into a memmove whenever possible. template struct __copy_backward_dispatch { typedef typename iterator_traits<_bidirectionaliter1>::iterator_category _cat; typedef typename iterator_traits<_bidirectionaliter1>::difference_type _distance; static _bidirectionaliter2 copy(_bidirectionaliter1 __first, _bidirectionaliter1 __last, _bidirectionaliter2 __result) { return __copy_backward(__first, __last, __result, _cat(), (_distance*) 0); } }; template struct __copy_backward_dispatch<_tp*, _tp*, __true_type> { static _tp* copy(const _tp* __first, const _tp* __last, _tp* __result) { const ptrdiff_t _num = __last - __first; memmove(__result - _num, __first, sizeof(_tp) * _num); return __result - _num; } }; template struct __copy_backward_dispatch { static _tp* copy(const _tp* __first, const _tp* __last, _tp* __result) { return __copy_backward_dispatch<_tp*, _tp*, __true_type> ::copy(__first, __last, __result); } }; template inline _bi2 copy_backward(_bi1 __first, _bi1 __last, _bi2 __result) { __stl_requires(_bi1, _bidirectionaliterator); __stl_requires(_bi2, _mutable_bidirectionaliterator); __stl_convertible(typename iterator_traits<_bi1>::value_type, typename iterator_traits<_bi2>::value_type); typedef typename __type_traits::value_type> ::has_trivial_assignment_operator _trivial; return __copy_backward_dispatch<_bi1, _bi2, _trivial> ::copy(__first, __last, __result); } #else /* __stl_class_partial_specialization */ // copy_backward算法:将[first,last)区间内的每一个元素,以逆性的方向复制到以result-1为起点,方向亦为逆行的区间上。 template inline _bi2 copy_backward(_bi1 __first, _bi1 __last, _bi2 __result) { return __copy_backward(__first, __last, __result, __iterator_category(__first), __distance_type(__first)); } #endif