STL源码剖析——STL算法之remove删除算法

桃扇骨 2022-08-12 19:29 283阅读 0赞

前言

由于在前文的《STL算法剖析》中,源码剖析非常多,不方便学习,也不方便以后复习,这里把这些算法进行归类,对他们单独的源码剖析进行讲解。本文介绍的STL算法中的remove删除算法,源码中介绍了函数remove、remove_copy、remove_if、remove_copy_if、unique、unique_copy。并对这些函数的源码进行详细的剖析,并适当给出使用例子,具体详见下面源码剖析。

remove移除算法源码剖析

  1. // remove, remove_if, remove_copy, remove_copy_if
  2. //移除[first,last)区间内所有与value值相等的元素,并不是真正的从容器中删除这些元素(原容器的内容不会改变)
  3. //而是将结果复制到一个以result为起始位置的容器中。新容器可以与原容器重叠
  4. template <class _InputIter, class _OutputIter, class _Tp>
  5. _OutputIter remove_copy(_InputIter __first, _InputIter __last,
  6. _OutputIter __result, const _Tp& __value) {
  7. __STL_REQUIRES(_InputIter, _InputIterator);
  8. __STL_REQUIRES(_OutputIter, _OutputIterator);
  9. __STL_REQUIRES_BINARY_OP(_OP_EQUAL, bool,
  10. typename iterator_traits<_InputIter>::value_type, _Tp);
  11. for ( ; __first != __last; ++__first)//遍历容器
  12. if (!(*__first == __value)) {//如果不相等
  13. *__result = *__first;//赋值给新容器
  14. ++__result;//新容器前进一个位置
  15. }
  16. return __result;
  17. }
  18. //移除[first,last)区间内被仿函数pred判断为true的元素,并不是真正的从容器中删除这些元素(原容器的内容不会改变)
  19. //而是将结果复制到一个以result为起始位置的容器中。新容器可以与原容器重叠
  20. template <class _InputIter, class _OutputIter, class _Predicate>
  21. _OutputIter remove_copy_if(_InputIter __first, _InputIter __last,
  22. _OutputIter __result, _Predicate __pred) {
  23. __STL_REQUIRES(_InputIter, _InputIterator);
  24. __STL_REQUIRES(_OutputIter, _OutputIterator);
  25. __STL_UNARY_FUNCTION_CHECK(_Predicate, bool,
  26. typename iterator_traits<_InputIter>::value_type);
  27. for ( ; __first != __last; ++__first)//遍历容器
  28. if (!__pred(*__first)) {//若pred判断为false
  29. *__result = *__first;//赋值给新容器
  30. ++__result;//新容器前进一个位置
  31. }
  32. return __result;
  33. }
  34. //移除[first,last)区间内所有与value值相等的元素,该操作不会改变容器大小,只是容器中元素值改变
  35. //即移除之后,重新整理容器的内容
  36. template <class _ForwardIter, class _Tp>
  37. _ForwardIter remove(_ForwardIter __first, _ForwardIter __last,
  38. const _Tp& __value) {
  39. __STL_REQUIRES(_ForwardIter, _Mutable_ForwardIterator);
  40. __STL_REQUIRES_BINARY_OP(_OP_EQUAL, bool,
  41. typename iterator_traits<_ForwardIter>::value_type, _Tp);
  42. __STL_CONVERTIBLE(_Tp, typename iterator_traits<_ForwardIter>::value_type);
  43. __first = find(__first, __last, __value);//利用顺序查找找出第一个与value相等的元素
  44. _ForwardIter __i = __first;
  45. //下面调用remove_copy
  46. return __first == __last ? __first
  47. : remove_copy(++__i, __last, __first, __value);
  48. }
  49. //移除[first,last)区间内所有被pred判断为true的元素,该操作不会改变容器大小,只是容器中元素值改变
  50. //即移除之后,重新整理容器的内容
  51. template <class _ForwardIter, class _Predicate>
  52. _ForwardIter remove_if(_ForwardIter __first, _ForwardIter __last,
  53. _Predicate __pred) {
  54. __STL_REQUIRES(_ForwardIter, _Mutable_ForwardIterator);
  55. __STL_UNARY_FUNCTION_CHECK(_Predicate, bool,
  56. typename iterator_traits<_ForwardIter>::value_type);
  57. __first = find_if(__first, __last, __pred);//利用顺序查找找出第一个与value相等的元素
  58. _ForwardIter __i = __first;
  59. //下面调用remove_copy_if
  60. return __first == __last ? __first
  61. : remove_copy_if(++__i, __last, __first, __pred);
  62. }
  63. //上面四个移除函数举例:
  64. /*
  65. #include <iostream> // std::cout
  66. #include <algorithm> // std::remove
  67. bool IsOdd (int i) { return ((i%2)==1); }
  68. int main () {
  69. int myints[] = {10,20,31,30,20,11,10,20}; // 10 20 31 30 20 11 10 20
  70. std::vector<int> myvector (8);
  71. std::remove_copy (myints,myints+8,myvector.begin(),20); // 10 31 30 11 10 0 0 0
  72. std::cout << "myvector contains:";
  73. for (std::vector<int>::iterator it=myvector.begin(); it!=myvector.end(); ++it)
  74. std::cout << ' ' << *it;
  75. std::cout << '\n';
  76. // bounds of range:
  77. int* pbegin = myints; // ^
  78. int* pend = myints+sizeof(myints)/sizeof(int); // ^ ^
  79. pend = std::remove (pbegin, pend, 20); // 10 31 30 11 10 ? ? ?
  80. // ^ ^
  81. std::cout << "range contains:";
  82. for (int* p=pbegin; p!=pend; ++p)
  83. std::cout << ' ' << *p;
  84. std::cout << '\n';
  85. std::vector<int> myvector2 (7);
  86. std::remove_copy_if (myints,myints+7,myvector2.begin(),IsOdd);
  87. std::cout << "myvector2 contains:";
  88. for (std::vector<int>::iterator it=myvector2.begin(); it!=myvector2.end(); ++it)
  89. std::cout << ' ' << *it;
  90. std::cout << '\n';
  91. pend = std::remove_if (pbegin, pend, IsOdd); // 10 30 10 ? ? ? ? ?
  92. // ^ ^
  93. std::cout << "the range contains:";
  94. for (int* p=pbegin; p!=pend; ++p)
  95. std::cout << ' ' << *p;
  96. std::cout << '\n';
  97. return 0;
  98. }
  99. Output:
  100. myvector contains: 10 31 30 11 10 0 0 0
  101. range contains: 10 31 30 11 10
  102. myvector2 contains: 10 30 10 10 0 0 0
  103. the range contains: 10 30 10
  104. */
  105. // unique and unique_copy
  106. template <class _InputIter, class _OutputIter, class _Tp>
  107. _OutputIter __unique_copy(_InputIter __first, _InputIter __last,
  108. _OutputIter __result, _Tp*) {
  109. _Tp __value = *__first;
  110. *__result = __value;
  111. while (++__first != __last)
  112. if (!(__value == *__first)) {
  113. __value = *__first;
  114. *++__result = __value;
  115. }
  116. return ++__result;
  117. }
  118. //若result类型为output_iterator_tag,则调用该函数
  119. template <class _InputIter, class _OutputIter>
  120. inline _OutputIter __unique_copy(_InputIter __first, _InputIter __last,
  121. _OutputIter __result,
  122. output_iterator_tag) {
  123. //判断first的value_type类型,根据不同类型调用不同函数
  124. return __unique_copy(__first, __last, __result, __VALUE_TYPE(__first));
  125. }
  126. //若result类型为forward_iterator_tag,则调用该函数
  127. template <class _InputIter, class _ForwardIter>
  128. _ForwardIter __unique_copy(_InputIter __first, _InputIter __last,
  129. _ForwardIter __result, forward_iterator_tag) {
  130. *__result = *__first;//记录第一个元素
  131. while (++__first != __last)//遍历区间
  132. //若不存在相邻重复元素,则继续记录到目标区result
  133. if (!(*__result == *__first))
  134. *++__result = *__first;//记录元素到目标区
  135. return ++__result;
  136. }
  137. unique_copy将区间[first,last)内元素复制到以result开头的区间上,但是如果存在相邻重复元素时,只复制其中第一个元素
  138. //和unique一样,这里也有两个版本
  139. /*
  140. 函数原型:
  141. equality (1)
  142. template <class InputIterator, class OutputIterator>
  143. OutputIterator unique_copy (InputIterator first, InputIterator last,
  144. OutputIterator result);
  145. predicate (2)
  146. template <class InputIterator, class OutputIterator, class BinaryPredicate>
  147. OutputIterator unique_copy (InputIterator first, InputIterator last,
  148. OutputIterator result, BinaryPredicate pred);
  149. */
  150. //版本一
  151. template <class _InputIter, class _OutputIter>
  152. inline _OutputIter unique_copy(_InputIter __first, _InputIter __last,
  153. _OutputIter __result) {
  154. __STL_REQUIRES(_InputIter, _InputIterator);
  155. __STL_REQUIRES(_OutputIter, _OutputIterator);
  156. __STL_REQUIRES(typename iterator_traits<_InputIter>::value_type,
  157. _EqualityComparable);
  158. if (__first == __last) return __result;
  159. //根据result迭代器的类型,调用不同的函数
  160. return __unique_copy(__first, __last, __result,
  161. __ITERATOR_CATEGORY(__result));
  162. }
  163. template <class _InputIter, class _OutputIter, class _BinaryPredicate,
  164. class _Tp>
  165. _OutputIter __unique_copy(_InputIter __first, _InputIter __last,
  166. _OutputIter __result,
  167. _BinaryPredicate __binary_pred, _Tp*) {
  168. __STL_BINARY_FUNCTION_CHECK(_BinaryPredicate, bool, _Tp, _Tp);
  169. _Tp __value = *__first;
  170. *__result = __value;
  171. while (++__first != __last)
  172. if (!__binary_pred(__value, *__first)) {
  173. __value = *__first;
  174. *++__result = __value;
  175. }
  176. return ++__result;
  177. }
  178. template <class _InputIter, class _OutputIter, class _BinaryPredicate>
  179. inline _OutputIter __unique_copy(_InputIter __first, _InputIter __last,
  180. _OutputIter __result,
  181. _BinaryPredicate __binary_pred,
  182. output_iterator_tag) {
  183. return __unique_copy(__first, __last, __result, __binary_pred,
  184. __VALUE_TYPE(__first));
  185. }
  186. template <class _InputIter, class _ForwardIter, class _BinaryPredicate>
  187. _ForwardIter __unique_copy(_InputIter __first, _InputIter __last,
  188. _ForwardIter __result,
  189. _BinaryPredicate __binary_pred,
  190. forward_iterator_tag) {
  191. __STL_BINARY_FUNCTION_CHECK(_BinaryPredicate, bool,
  192. typename iterator_traits<_ForwardIter>::value_type,
  193. typename iterator_traits<_InputIter>::value_type);
  194. *__result = *__first;
  195. while (++__first != __last)
  196. if (!__binary_pred(*__result, *__first)) *++__result = *__first;
  197. return ++__result;
  198. }
  199. //版本二
  200. template <class _InputIter, class _OutputIter, class _BinaryPredicate>
  201. inline _OutputIter unique_copy(_InputIter __first, _InputIter __last,
  202. _OutputIter __result,
  203. _BinaryPredicate __binary_pred) {
  204. __STL_REQUIRES(_InputIter, _InputIterator);
  205. __STL_REQUIRES(_OutputIter, _OutputIterator);
  206. if (__first == __last) return __result;
  207. //根据result迭代器的类型,调用不同的函数
  208. return __unique_copy(__first, __last, __result, __binary_pred,
  209. __ITERATOR_CATEGORY(__result));
  210. }
  211. //移除区间[first,last)相邻连续重复的元素
  212. //unique有两个版本
  213. //功能:Removes all but the first element from every consecutive group of equivalent elements in the range [first,last).
  214. /*
  215. 函数原型:
  216. equality (1):版本一采用operator==
  217. template <class ForwardIterator>
  218. ForwardIterator unique (ForwardIterator first, ForwardIterator last);
  219. predicate (2):版本二采用pred操作
  220. template <class ForwardIterator, class BinaryPredicate>
  221. ForwardIterator unique (ForwardIterator first, ForwardIterator last,
  222. BinaryPredicate pred);
  223. */
  224. //版本一
  225. template <class _ForwardIter>
  226. _ForwardIter unique(_ForwardIter __first, _ForwardIter __last) {
  227. __STL_REQUIRES(_ForwardIter, _Mutable_ForwardIterator);
  228. __STL_REQUIRES(typename iterator_traits<_ForwardIter>::value_type,
  229. _EqualityComparable);
  230. __first = adjacent_find(__first, __last);//找出第一个相邻元素的起始位置
  231. return unique_copy(__first, __last, __first);//调用unique_copy完成操作
  232. }
  233. //版本二
  234. template <class _ForwardIter, class _BinaryPredicate>
  235. _ForwardIter unique(_ForwardIter __first, _ForwardIter __last,
  236. _BinaryPredicate __binary_pred) {
  237. __STL_REQUIRES(_ForwardIter, _Mutable_ForwardIterator);
  238. __STL_BINARY_FUNCTION_CHECK(_BinaryPredicate, bool,
  239. typename iterator_traits<_ForwardIter>::value_type,
  240. typename iterator_traits<_ForwardIter>::value_type);
  241. __first = adjacent_find(__first, __last, __binary_pred);//找出第一个相邻元素的起始位置
  242. return unique_copy(__first, __last, __first, __binary_pred);//调用unique_copy完成操作
  243. }

参考资料:

《STL源码剖析》侯捷

发表评论

表情:
评论列表 (有 0 条评论,283人围观)

还没有评论,来说两句吧...

相关阅读

    相关 STL剖析】Sort算法

    前言:sort算法必须拿出来单独将,因为它是STL所有算法中最复杂最庞大的一个,就像我肯定会把copy算法单独列出来一样,这两个算法太重要了。 提示:STL算法特点是,前两个