• C++11标准模板(STL)- 算法(std::unique)


    定义于头文件 

    算法库提供大量用途的函数(例如查找、排序、计数、操作),它们在元素范围上操作。注意范围定义为 [first, last) ,其中 last 指代要查询或修改的最后元素的后一个元素。

    移除范围内的连续重复元素

    std::unique

    template< class ForwardIt >
    ForwardIt unique( ForwardIt first, ForwardIt last );

    (1)(C++20 前)

    template< class ForwardIt >
    constexpr ForwardIt unique( ForwardIt first, ForwardIt last );

    (C++20 起)

    template< class ExecutionPolicy, class ForwardIt >
    ForwardIt unique( ExecutionPolicy&& policy, ForwardIt first, ForwardIt last );

    (2)(C++17 起)

    template< class ForwardIt, class BinaryPredicate >
    ForwardIt unique( ForwardIt first, ForwardIt last, BinaryPredicate p );

    (3)(C++20 前)

    template< class ForwardIt, class BinaryPredicate >
    constexpr ForwardIt unique( ForwardIt first, ForwardIt last, BinaryPredicate p );

    (C++20 起)

    template< class ExecutionPolicy, class ForwardIt, class BinaryPredicate >
    ForwardIt unique( ExecutionPolicy&& policy, ForwardIt first, ForwardIt last, BinaryPredicate p );

    (4)(C++17 起)

    从来自范围 [first, last) 的相继等价元素组消除首元素外的元素,并返回范围的新逻辑结尾的尾后迭代器。

    通过用覆写要被擦除的元素的方式迁移范围中的元素进行移除。保持剩余元素的相对顺序,且不更改容器的物理大小。指向范围的新逻辑结尾和物理结尾之间元素的迭代器仍然可解引用,但元素自身拥有未指定值。调用 unique 典型地后随调用容器的 erase 方法,它擦除未指定值并减小容器的物理大小,以匹配其新的逻辑大小。

    1) 用 operator== 比较元素。若它不是等价关系则行为未定义。

    3) 用给定的谓词 p 比较元素。若它不是等价关系则行为未定义。

    2,4) 同 (1,3) ,但按照 policy 执行。这些重载仅若 std::is_execution_policy_v> 为 true 才参与重载决议。

    参数

    first, last-要处理的元素范围
    policy-所用的执行策略。细节见执行策略。
    p-若元素应被当做相等则返回 ​true 的二元谓词。

    谓词函数的签名应等价于如下:

     bool pred(const Type1 &a, const Type2 &b);

    虽然签名不必有 const & ,函数也不能修改传递给它的对象,而且必须接受(可为 const 的)类型 Type1Type2 的值,无关乎值类别(从而不允许 Type1 & ,亦不允许 Type1 ,除非 Type1 的移动等价于复制 (C++11 起))。
    类型 Type1 与 Type2 必须使得 ForwardIt 类型的对象能在解引用后隐式转换到这两个类型。 ​

    类型要求
    - ForwardIt 必须满足遗留向前迭代器 (LegacyForwardIterator) 的要求。
    - 解引用 ForwardIt 结果的类型必须满足可移动赋值 (MoveAssignable) 的要求。

    返回值

    指向范围新结尾的向前迭代器。

    复杂度

    对于非空范围,准确应用 std::distance(first,last) -1 次对应的谓词。

    异常

    拥有名为 ExecutionPolicy 的模板形参的重载按下列方式报告错误:

    • 若作为算法一部分调用的函数的执行抛出异常,且 ExecutionPolicy 为标准策略之一,则调用 std::terminate 。对于任何其他 ExecutionPolicy ,行为是实现定义的。
    • 若算法无法分配内存,则抛出 std::bad_alloc 。

    可能的实现

    版本一

    1. template<class ForwardIt>
    2. ForwardIt unique(ForwardIt first, ForwardIt last)
    3. {
    4. if (first == last)
    5. return last;
    6. ForwardIt result = first;
    7. while (++first != last) {
    8. if (!(*result == *first) && ++result != first) {
    9. *result = std::move(*first);
    10. }
    11. }
    12. return ++result;
    13. }

    版本二

    1. template<class ForwardIt, class BinaryPredicate>
    2. ForwardIt unique(ForwardIt first, ForwardIt last, BinaryPredicate p)
    3. {
    4. if (first == last)
    5. return last;
    6. ForwardIt result = first;
    7. while (++first != last) {
    8. if (!p(*result, *first) && ++result != first) {
    9. *result = std::move(*first);
    10. }
    11. }
    12. return ++result;
    13. }

    调用示例

    1. #include <iostream>
    2. #include <algorithm>
    3. #include <functional>
    4. #include <vector>
    5. #include <iterator>
    6. using namespace std;
    7. struct Cell
    8. {
    9. int x;
    10. int y;
    11. Cell &operator +=(const Cell &cell)
    12. {
    13. x += cell.x;
    14. y += cell.y;
    15. return *this;
    16. }
    17. bool operator ==(const Cell &cell)
    18. {
    19. return x == cell.x && y == cell.y;
    20. }
    21. bool operator <(const Cell &cell)
    22. {
    23. if (x == cell.x)
    24. {
    25. return y < cell.y;
    26. }
    27. else
    28. {
    29. return x < cell.y;
    30. }
    31. }
    32. };
    33. std::ostream &operator<<(std::ostream &os, const Cell &cell)
    34. {
    35. os << "{" << cell.x << "," << cell.y << "}";
    36. return os;
    37. }
    38. int main()
    39. {
    40. auto func1 = [](Cell & cell, const Cell & t)
    41. {
    42. cell += t;
    43. return cell;
    44. };
    45. Cell cell{99, 100};
    46. Cell t{2, 3};
    47. auto func2 = std::bind(func1, cell, t);
    48. vector<Cell> cells(8);
    49. std::generate(cells.begin(), cells.begin() + cells.size() / 3, func2);
    50. std::generate(cells.begin() + cells.size() / 3, cells.end(), func2);
    51. std::sort(cells.begin(), cells.end());//排序
    52. std::cout << "original : ";
    53. std::copy(cells.begin(), cells.end(), std::ostream_iterator<Cell>(std::cout, " "));
    54. std::cout << std::endl;
    55. std::cout << "unique : ";
    56. auto last = std::unique(cells.begin(), cells.end());
    57. std::copy(cells.begin(), cells.end(), std::ostream_iterator<Cell>(std::cout, " "));
    58. std::cout << std::endl;
    59. std::cout << "erase : ";
    60. cells.erase(last, cells.end());
    61. std::copy(cells.begin(), cells.end(), std::ostream_iterator<Cell>(std::cout, " "));
    62. std::cout << std::endl;
    63. std::cout << std::endl;
    64. auto func3 = [](const Cell & a, const Cell & b)
    65. {
    66. return a.x == b.x && a.y == b.y;
    67. };
    68. cells.resize(8);
    69. std::generate(cells.begin(), cells.begin() + cells.size() / 3, func2);
    70. std::generate(cells.begin() + cells.size() / 3, cells.end(), func2);
    71. std::sort(cells.begin(), cells.end());//排序
    72. std::cout << "func original : ";
    73. std::copy(cells.begin(), cells.end(), std::ostream_iterator<Cell>(std::cout, " "));
    74. std::cout << std::endl;
    75. std::cout << "func unique : ";
    76. last = std::unique(cells.begin(), cells.end(), func3);
    77. std::copy(cells.begin(), cells.end(), std::ostream_iterator<Cell>(std::cout, " "));
    78. std::cout << std::endl;
    79. std::cout << "func erase : ";
    80. cells.erase(last, cells.end());
    81. std::copy(cells.begin(), cells.end(), std::ostream_iterator<Cell>(std::cout, " "));
    82. std::cout << std::endl;
    83. return 0;
    84. }

    输出

  • 相关阅读:
    【GPTs分享】GPTs分享之Image Recreate | img2img​
    spring boot logback.xml文件配置,info、error隔离
    UG\NX二次开发 信息窗口的一些操作 NXOpen/ListingWindow
    猿创征文|信息抽取(2)——pytorch实现Bert-BiLSTM-CRF、Bert-CRF模型进行实体抽取
    @Transactional初探
    什么是Vue?什么又是vue指令?
    Python:Jenkins包
    Oculus quest2 指南or劝退?
    Flutter Text 实现下划线、波浪线、删除线、背景色、渐变文字、阴影、描边、空心字
    零基础学前端(七)将项目发布成网站
  • 原文地址:https://blog.csdn.net/qq_40788199/article/details/127719278