• C++ 学习系列 -- 标准库常用得 algorithm function


    一   前言

    c++ 标准库中提供了许多操作数据结构:vector、list、deque、map、set 等函数,学习并了解这些常用函数对于我们理解 c++ 的一些设计模式有着重要的作用。

    二  常用的 algorithm function 源码

    源代码位置:

    bits/stl_algo.h

    1.  accumulate

    1. /**
    2. * @brief Accumulate values in a range.
    3. *
    4. * Accumulates the values in the range [first,last) using operator+(). The
    5. * initial value is @a init. The values are processed in order.
    6. *
    7. * @param __first Start of range.
    8. * @param __last End of range.
    9. * @param __init Starting value to add other values to.
    10. * @return The final sum.
    11. */
    12. template<typename _InputIterator, typename _Tp>
    13. inline _Tp
    14. accumulate(_InputIterator __first, _InputIterator __last, _Tp __init)
    15. {
    16. for (; __first != __last; ++__first)
    17. __init = __init + *__first;
    18. return __init;
    19. }
    20. /**
    21. * @brief Accumulate values in a range with operation.
    22. *
    23. * Accumulates the values in the range [first,last) using the function
    24. * object @p __binary_op. The initial value is @p __init. The values are
    25. * processed in order.
    26. *
    27. * @param __first Start of range.
    28. * @param __last End of range.
    29. * @param __init Starting value to add other values to.
    30. * @param __binary_op Function object to accumulate with.
    31. * @return The final sum.
    32. */
    33. template<typename _InputIterator, typename _Tp, typename _BinaryOperation>
    34. inline _Tp
    35. accumulate(_InputIterator __first, _InputIterator __last, _Tp __init,
    36. _BinaryOperation __binary_op)
    37. {
    38. for (; __first != __last; ++__first)
    39. __init = __binary_op(__init, *__first);
    40. return __init;
    41. }

    accumulate 函数又两个重载版本:

    第一个函数的第三个参数是初始值,是单纯的将 数据累加到初始值 init 上;

    第二个函数的第三个参数是 “累加”  的初始值,第四个参数是函数或者仿函数对象,是可以自定义 “累加” 的函数 binary_op ,该函数的作用是将迭代器中的每个元素都执行一遍 binar_op 后,将结果 “累加” 到 初始值 init 上

    2. for_each

    1. /**
    2. * @brief Apply a function to every element of a sequence.
    3. * @ingroup non_mutating_algorithms
    4. * @param __first An input iterator.
    5. * @param __last An input iterator.
    6. * @param __f A unary function object.
    7. * @return @p __f
    8. *
    9. * Applies the function object @p __f to each element in the range
    10. * @p [first,last). @p __f must not modify the order of the sequence.
    11. * If @p __f has a return value it is ignored.
    12. */
    13. template<typename _InputIterator, typename _Function>
    14. _Function
    15. for_each(_InputIterator __first, _InputIterator __last, _Function __f)
    16. {
    17. for (; __first != __last; ++__first)
    18. __f(*__first);
    19. return __f; // N.B. [alg.foreach] says std::move(f) but it's redundant.
    20. }

          for_each 函数第三个函数是函数或者仿函数对象,该函数作用是遍历迭代器,并对迭代器中的每个元素分别执行一次 _Function ,_Function 可以用户自定义

    3. replace/replace_if

    1. /**
    2. * @brief Replace each occurrence of one value in a sequence with another
    3. * value.
    4. * @ingroup mutating_algorithms
    5. * @param __first A forward iterator.
    6. * @param __last A forward iterator.
    7. * @param __old_value The value to be replaced.
    8. * @param __new_value The replacement value.
    9. * @return replace() returns no value.
    10. *
    11. * For each iterator @c i in the range @p [__first,__last) if @c *i ==
    12. * @p __old_value then the assignment @c *i = @p __new_value is performed.
    13. */
    14. template<typename _ForwardIterator, typename _Tp>
    15. void
    16. replace(_ForwardIterator __first, _ForwardIterator __last,
    17. const _Tp& __old_value, const _Tp& __new_value)
    18. {
    19. for (; __first != __last; ++__first)
    20. if (*__first == __old_value)
    21. *__first = __new_value;
    22. }
    23. /**
    24. * @brief Replace each value in a sequence for which a predicate returns
    25. * true with another value.
    26. * @ingroup mutating_algorithms
    27. * @param __first A forward iterator.
    28. * @param __last A forward iterator.
    29. * @param __pred A predicate.
    30. * @param __new_value The replacement value.
    31. * @return replace_if() returns no value.
    32. *
    33. * For each iterator @c i in the range @p [__first,__last) if @p __pred(*i)
    34. * is true then the assignment @c *i = @p __new_value is performed.
    35. */
    36. template<typename _ForwardIterator, typename _Predicate, typename _Tp>
    37. void
    38. replace_if(_ForwardIterator __first, _ForwardIterator __last,
    39. _Predicate __pred, const _Tp& __new_value)
    40. {
    41. for (; __first != __last; ++__first)
    42. if (__pred(*__first))
    43. *__first = __new_value;
    44. }

        3.1  replace 函数 第三个参数传入的是待被替换的旧值,第四个参数是 被替换后的新值,该函数执行后,会把迭代器中所有值等于旧值得元素都替换为新值

        3.2  replace_if 函数第三个参数是一个函数对象,第四个参数是替换后得新值。该函数得作用是将迭代器中所有符合传入函数规则得旧值替换为新值。

    4. count/count_if

    1. template<typename _InputIterator, typename _Predicate>
    2. typename iterator_traits<_InputIterator>::difference_type
    3. __count_if(_InputIterator __first, _InputIterator __last, _Predicate __pred)
    4. {
    5. typename iterator_traits<_InputIterator>::difference_type __n = 0;
    6. for (; __first != __last; ++__first)
    7. if (__pred(__first))
    8. ++__n;
    9. return __n;
    10. }
    11. /**
    12. * @brief Count the number of copies of a value in a sequence.
    13. * @ingroup non_mutating_algorithms
    14. * @param __first An input iterator.
    15. * @param __last An input iterator.
    16. * @param __value The value to be counted.
    17. * @return The number of iterators @c i in the range @p [__first,__last)
    18. * for which @c *i == @p __value
    19. */
    20. template<typename _InputIterator, typename _Tp>
    21. inline typename iterator_traits<_InputIterator>::difference_type
    22. count(_InputIterator __first, _InputIterator __last, const _Tp& __value)
    23. {
    24. return std::__count_if(__first, __last,
    25. __gnu_cxx::__ops::__iter_equals_val(__value));
    26. }
    27. /**
    28. * @brief Count the elements of a sequence for which a predicate is true.
    29. * @ingroup non_mutating_algorithms
    30. * @param __first An input iterator.
    31. * @param __last An input iterator.
    32. * @param __pred A predicate.
    33. * @return The number of iterators @c i in the range @p [__first,__last)
    34. * for which @p __pred(*i) is true.
    35. */
    36. template<typename _InputIterator, typename _Predicate>
    37. inline typename iterator_traits<_InputIterator>::difference_type
    38. count_if(_InputIterator __first, _InputIterator __last, _Predicate __pred)
    39. {
    40. return std::__count_if(__first, __last,
    41. __gnu_cxx::__ops::__pred_iter(__pred));
    42. }

       1. __count_if 函数第三个传入参数是一个函数或者仿函数对象,该函数的作用是遍历迭代器,统计有符合传入函数的元素个数

      2. count 函数第三个参数是一个值,该函数作用是遍历迭代器,统计与传入值相等的元素个数

      3. count_if 直接调用了 __count_if ,作用与 1 中描述相同

    5. find/find_if

    1. /// This is an overload used by find algos for the Input Iterator case.
    2. template<typename _InputIterator, typename _Predicate>
    3. inline _InputIterator
    4. __find_if(_InputIterator __first, _InputIterator __last,
    5. _Predicate __pred, input_iterator_tag)
    6. {
    7. while (__first != __last && !__pred(__first))
    8. ++__first;
    9. return __first;
    10. }
    11. /// This is an overload used by find algos for the RAI case.
    12. template<typename _RandomAccessIterator, typename _Predicate>
    13. _RandomAccessIterator
    14. __find_if(_RandomAccessIterator __first, _RandomAccessIterator __last,
    15. _Predicate __pred, random_access_iterator_tag)
    16. {
    17. typename iterator_traits<_RandomAccessIterator>::difference_type
    18. __trip_count = (__last - __first) >> 2;
    19. for (; __trip_count > 0; --__trip_count)
    20. {
    21. if (__pred(__first))
    22. return __first;
    23. ++__first;
    24. if (__pred(__first))
    25. return __first;
    26. ++__first;
    27. if (__pred(__first))
    28. return __first;
    29. ++__first;
    30. if (__pred(__first))
    31. return __first;
    32. ++__first;
    33. }
    34. switch (__last - __first)
    35. {
    36. case 3:
    37. if (__pred(__first))
    38. return __first;
    39. ++__first;
    40. case 2:
    41. if (__pred(__first))
    42. return __first;
    43. ++__first;
    44. case 1:
    45. if (__pred(__first))
    46. return __first;
    47. ++__first;
    48. case 0:
    49. default:
    50. return __last;
    51. }
    52. }
    53. template<typename _Iterator, typename _Predicate>
    54. inline _Iterator
    55. __find_if(_Iterator __first, _Iterator __last, _Predicate __pred)
    56. {
    57. return __find_if(__first, __last, __pred,
    58. std::__iterator_category(__first));
    59. }
    60. /**
    61. * @brief Find the first occurrence of a value in a sequence.
    62. * @ingroup non_mutating_algorithms
    63. * @param __first An input iterator.
    64. * @param __last An input iterator.
    65. * @param __val The value to find.
    66. * @return The first iterator @c i in the range @p [__first,__last)
    67. * such that @c *i == @p __val, or @p __last if no such iterator exists.
    68. */
    69. template<typename _InputIterator, typename _Tp>
    70. inline _InputIterator
    71. find(_InputIterator __first, _InputIterator __last,
    72. const _Tp& __val)
    73. {
    74. return std::__find_if(__first, __last,
    75. __gnu_cxx::__ops::__iter_equals_val(__val));
    76. }
    77. /**
    78. * @brief Find the first element in a sequence for which a
    79. * predicate is true.
    80. * @ingroup non_mutating_algorithms
    81. * @param __first An input iterator.
    82. * @param __last An input iterator.
    83. * @param __pred A predicate.
    84. * @return The first iterator @c i in the range @p [__first,__last)
    85. * such that @p __pred(*i) is true, or @p __last if no such iterator exists.
    86. */
    87. template<typename _InputIterator, typename _Predicate>
    88. inline _InputIterator
    89. find_if(_InputIterator __first, _InputIterator __last,
    90. _Predicate __pred)
    91. {
    92. return std::__find_if(__first, __last,
    93. __gnu_cxx::__ops::__pred_iter(__pred));
    94. }

        1.  第一个 __find_if 函数的第三个参数是函数或者仿函数,第四个参数是 input_iterator_tag (该参数连对应的变量都没有,只有一个类型,其主要作用是为了在重载时与第二个 __find_if 进行区分,毕竟 顺序迭代查找与可以随机访问的查找效率上是不同的),该函数的作用是遍历迭代器,从中找出与传入值相等的元素,若是存在则返回该元素的迭代器,否则返回 _last

     2. 第二个 __find_if 函数的第三个参数是 函数或者仿函数,第四个参数是 random_access_iterator_tag (该参数连对应的变量都没有,只有一个类型,其主要作用是为了在重载时与第二个 __find_if 进行区分,毕竟 顺序迭代查找与可以随机访问的查找效率上是不同的),该函数的作用是历迭代器,从中找出与传入值相等的元素,若是存在则返回该元素的迭代器,否则返回 _last,效率上应该比第一个 __find_if 高一些。

    3. 第三个 __find_if 函数的第三个参数是 函数或者仿函数,该函数的作用是个中转,其底层调用的是第一个或者第二个函数,只不过多了个询问迭代器类型的操作:std::__iterator_category

    4. find 函数第三个参数 const _Tp&是传入一个待查找的值,该函数的作用是若是查找到与该值相等的元素,则返回对应的迭代器,否则返回 __last

    5. find_if  函数的第三个参数是 函数或者仿函数,该函数底层调用的是第三个函数 __find_if ,该函数的作用是若是查到元素符合传入的函数规则则返回该元素的迭代器,否则返回 __last

    6. sort

    待补充

    7. binary_search

    1. template<typename _ForwardIterator, typename _Tp, typename _Compare>
    2. _ForwardIterator
    3. __lower_bound(_ForwardIterator __first, _ForwardIterator __last,
    4. const _Tp& __val, _Compare __comp)
    5. {
    6. typedef typename iterator_traits<_ForwardIterator>::difference_type
    7. _DistanceType;
    8. _DistanceType __len = std::distance(__first, __last);
    9. while (__len > 0)
    10. {
    11. _DistanceType __half = __len >> 1;
    12. _ForwardIterator __middle = __first;
    13. std::advance(__middle, __half);
    14. if (__comp(__middle, __val))
    15. {
    16. __first = __middle;
    17. ++__first;
    18. __len = __len - __half - 1;
    19. }
    20. else
    21. __len = __half;
    22. }
    23. return __first;
    24. }
    25. /**
    26. * @brief Finds the first position in which @a val could be inserted
    27. * without changing the ordering.
    28. * @param __first An iterator.
    29. * @param __last Another iterator.
    30. * @param __val The search term.
    31. * @return An iterator pointing to the first element not less
    32. * than @a val, or end() if every element is less than
    33. * @a val.
    34. * @ingroup binary_search_algorithms
    35. */
    36. template<typename _ForwardIterator, typename _Tp>
    37. inline _ForwardIterator
    38. lower_bound(_ForwardIterator __first, _ForwardIterator __last,
    39. const _Tp& __val)
    40. {
    41. return std::__lower_bound(__first, __last, __val,
    42. __gnu_cxx::__ops::__iter_less_val());
    43. }
    44. /**
    45. * @brief Determines whether an element exists in a range.
    46. * @ingroup binary_search_algorithms
    47. * @param __first An iterator.
    48. * @param __last Another iterator.
    49. * @param __val The search term.
    50. * @return True if @p __val (or its equivalent) is in [@p
    51. * __first,@p __last ].
    52. *
    53. * Note that this does not actually return an iterator to @p __val. For
    54. * that, use std::find or a container's specialized find member functions.
    55. */
    56. template<typename _ForwardIterator, typename _Tp>
    57. bool
    58. binary_search(_ForwardIterator __first, _ForwardIterator __last,
    59. const _Tp& __val)
    60. {
    61. _ForwardIterator __i
    62. = std::__lower_bound(__first, __last, __val,
    63. __gnu_cxx::__ops::__iter_less_val());
    64. return __i != __last && !(__val < *__i);
    65. }
    66. /**
    67. * @brief Determines whether an element exists in a range.
    68. * @ingroup binary_search_algorithms
    69. * @param __first An iterator.
    70. * @param __last Another iterator.
    71. * @param __val The search term.
    72. * @param __comp A functor to use for comparisons.
    73. * @return True if @p __val (or its equivalent) is in @p [__first,__last].
    74. *
    75. * Note that this does not actually return an iterator to @p __val. For
    76. * that, use std::find or a container's specialized find member functions.
    77. *
    78. * The comparison function should have the same effects on ordering as
    79. * the function used for the initial sort.
    80. */
    81. template<typename _ForwardIterator, typename _Tp, typename _Compare>
    82. bool
    83. binary_search(_ForwardIterator __first, _ForwardIterator __last,
    84. const _Tp& __val, _Compare __comp)
    85. {
    86. _ForwardIterator __i
    87. = std::__lower_bound(__first, __last, __val,
    88. __gnu_cxx::__ops::__iter_comp_val(__comp));
    89. return __i != __last && !bool(__comp(__val, *__i));
    90. }

    1. 第一个 binary_search 函数的  三个参数 __val 是查找的目标值,该函数的作用是利用二分查找法查找目标值,若是查找到目标值,则返回 true,否则返回 false

    2. 第二个 binar_search 函数的第三个参数 __val 是查找的目标值 ,第四个参数 __comp   是函数或者仿函数对象,该函数 是利用二分查找法查找目标值,若是查找到某个值使得 __comp(__val, target) 返回 true,则说明查到了目标值,此时返回 true,否则返回 法拉瑟

    三   示例

    1. #include
    2. #include
    3. using namespace std;
    4. struct PredicateReplace: public std::unary_function<int, bool>
    5. {
    6. bool operator()(const int x) const
    7. {
    8. return x % 3 == 0;
    9. }
    10. };
    11. struct PredictCount: public std::unary_function<int, bool>
    12. {
    13. bool operator()(int x)
    14. {
    15. return x % 3 == 1;
    16. }
    17. };
    18. struct PredictBinarySearch:public std::binary_function<int, int, bool>
    19. {
    20. bool operator()(int x, int y)
    21. {
    22. std::cout << "x: " << x << ", y: " << y << std::endl;
    23. return x < y;
    24. }
    25. };
    26. int main()
    27. {
    28. std::vector<int> vec = {10, 50, 60, 20, 30, 40};
    29. int init = 0;
    30. // 1. accumulate
    31. std::cout << "------ test accumulate ------" << std::endl;
    32. std::cout << std::accumulate(vec.begin(), vec.end(), init) << std::endl; // 210
    33. init = 600;
    34. std::cout << std::accumulate(vec.begin(), vec.end(), init, std::minus<int>()) << std::endl; // 390
    35. std::cout << "------ test accumulate ------" << std::endl;
    36. // 2. for_each
    37. struct printVal{
    38. void operator()(int x){
    39. std::cout << x << " ";
    40. }
    41. };
    42. std::cout << "------ test for_each ------" << std::endl;
    43. std::for_each(vec.begin(), vec.end(),printVal());
    44. cout << endl;
    45. std::cout << "------ test for_each ------" << std::endl;
    46. // 3. replace replace_if
    47. std::cout << "------ test replace ------" << std::endl;
    48. std::replace(vec.begin(), vec.end(), 50, 90);
    49. std::for_each(vec.begin(), vec.end(),printVal());
    50. cout << endl;
    51. std::vector<int> vec_replace1 = vec;
    52. std::replace_if(vec_replace1.begin(), vec_replace1.end(), PredicateReplace(), 666);
    53. std::for_each(vec_replace1.begin(), vec_replace1.end(),printVal());
    54. cout << endl;
    55. PredicateReplace pp;
    56. std::vector<int> vec_replace2 = vec;
    57. std::replace_if(vec_replace2.begin(), vec_replace2.end(), std::not1(pp), 666);
    58. std::for_each(vec_replace2.begin(), vec_replace2.end(),printVal());
    59. cout << endl;
    60. std::cout << "------ test replace ------" << std::endl;
    61. // 4. count count_if
    62. std::cout << "------ test count ------" << std::endl;
    63. std::vector<int> vec_cout1 = vec;
    64. std::cout << std::count(vec_cout1.begin(), vec_cout1.end(), 60) << std::endl;
    65. std::cout << std::count_if(vec_cout1.begin(), vec_cout1.end(), PredictCount()) << std::endl;
    66. std::cout << "------ test count ------" << std::endl;
    67. // 5. find find_if
    68. std::cout << "------ test find ------" << std::endl;
    69. auto iter = std::find(vec.begin(), vec.end(), 30);
    70. if(iter != vec.end())
    71. std::cout << *iter << std::endl;
    72. iter = std::find_if(vec.begin(), vec.end(), PredictCount());
    73. if(iter != vec.end())
    74. std::cout << *iter << std::endl;
    75. std::cout << "------ test find ------" << std::endl;
    76. // 6. sort
    77. std::cout << "------ test sort ------" << std::endl;
    78. std::sort(vec.begin(), vec.end(), std::greater<int>());
    79. std::for_each(vec.begin(), vec.end(),printVal()); // 60 50 40 30 20 10
    80. cout << endl;
    81. std::sort(vec.begin(), vec.end(), std::less<int>()); // 10 20 30 40 50 60
    82. std::for_each(vec.begin(), vec.end(),printVal());
    83. cout << endl;
    84. std::cout << "------ test sort ------" << std::endl;
    85. // 7. binary_search
    86. std::cout << "------ test binary_search ------" << std::endl;
    87. bool isExists = std::binary_search(vec.begin(), vec.end(), 50);
    88. if(isExists)
    89. {
    90. std::cout << "50 is existed. " << std::endl;
    91. }
    92. else
    93. {
    94. std::cout << "50 is not existed. " << std::endl;
    95. }
    96. bool isExists2 = std::binary_search(vec.begin(), vec.end(), 60, PredictBinarySearch());
    97. if(isExists2)
    98. {
    99. std::cout << "x == 60 is existed. " << std::endl;
    100. }
    101. else
    102. {
    103. std::cout << "x == 60 is not existed. " << std::endl;
    104. }
    105. std::cout << "------ test binary_search ------" << std::endl;
    106. return 0;
    107. }

  • 相关阅读:
    【Linux】部署单体项目以及前后端分离项目(项目部署)
    java中log使用总结
    扩散模型加持下,机器人模型DALL-E-Bot可以轻松完成自主重新排列任务
    openpyxl应用
    【Java】线程池源码解析
    《30天吃掉那只 TensorFlow2.0》五、TensorFlow的中阶API
    第 1 课 Python 的输出!
    Springboot餐饮点餐系统毕业设计源码301749
    SpringBoot 集成 kaptcha 验证码
    Qt ffmpeg音视频转换工具
  • 原文地址:https://blog.csdn.net/qq_33775774/article/details/134095736