C++标准模板库(STL)算法:<algorithm>

前言:

        C++标准模板库(STL)是每个C++程序员的宝库,它提供了一系列广泛使用的算法,这些算法都包含在 `<algorithm>` 头文件中。STL算法与容器无缝集成,允许开发者编写更加简洁、可读和高效的代码。本文将深入探讨这些算法,并了解如何使用它们来解决实际问题。

算法:

1. 非修改性算法

        非修改性算法不会更改容器的内容,主要用于读取或检查容器的内容。例如,`std::for_each` 允许我们对容器中的每个元素应用函数,而 `std::count_if` 可以帮助我们统计满足特定条件的元素数量。这类算法在数据分析和检查中特别有用。

  • `std::for_each`: 对范围内的每个元素应用一个函数。
  • `std::count`, `std::count_if`: 计算满足某个条件的元素的数量。
  • `std::find`, `std::find_if`, `std::find_if_not`: 查找满足某个条件的元素。
  • `std::equal`: 检查两个序列是否相等。

1.1 for_each

        对范围内的每个元素应用一个函数。

#include <algorithm>
#include <iostream>
#include <vector>

int main() {
    std::vector<int> v = {1, 2, 3, 4, 5};

    std::for_each(v.begin(), v.end(), [](int &n) {
        n *= 2;
    });

    for (const auto &i: v) std::cout << i << ' '; // 输出:2 4 6 8 10
}

1.2 count ,count_if

        计算满足某个条件的元素的数量。

#include <algorithm>
#include <iostream>
#include <vector>

int main() {
    std::vector<int> v = {1, 2, 3, 4, 5};

    int count = std::count_if(v.begin(), v.end(), [](int n) {
        return n % 2 == 0;
    });

    std::cout << "Number of even elements: " << count; // 输出:Number of even elements: 2
}

1.3 find,find_if,find_if_not

        查找满足某个条件的元素。

#include <algorithm>
#include <iostream>
#include <vector>

int main() {
    std::vector<int> v = {1, 2, 3, 4, 5};

    auto it = std::find_if(v.begin(), v.end(), [](int n) {
        return n > 3;
    });

    if (it != v.end()) std::cout << "Found value greater than 3: " << *it; // 输出:Found value greater than 3: 4
}

1.4 equal

        检查两个序列是否相等。

#include <algorithm>
#include <iostream>
#include <vector>

int main() {
    std::vector<int> v1 = {1, 2, 3, 4, 5};
    std::vector<int> v2 = {1, 2, 3, 4, 5};

    if (std::equal(v1.begin(), v1.end(), v2.begin())) {
        std::cout << "The sequences are equal.\n"; // 输出:The sequences are equal.
    } else {
        std::cout << "The sequences are not equal.\n";
    }
}

2. 修改性算法

        修改性算法会改变容器的内容。例如,我们可以使用 `std::copy` 将一个容器的内容复制到另一个容器中,或使用 `std::transform` 来对容器中的每个元素应用一个函数并存储结果。这类算法在数据处理和转换中非常实用。

  • `std::copy`: 复制一个范围内的元素到另一个位置。
  • `std::move`: 移动一个范围内的元素到另一个位置。
  • `std::transform`: 对范围内的每个元素应用一个函数,并将结果存储到另一个位置。
  • `std::fill`, `std::fill_n`: 用给定值填充一个范围内的元素。
  • `std::replace`, `std::replace_if`: 替换满足某个条件的所有元素。

2.1 copy

        复制一个范围内的元素到另一个位置。

#include <algorithm>
#include <iostream>
#include <vector>

int main() {
    std::vector<int> src = {1, 2, 3, 4, 5};
    std::vector<int> dest(5);

    std::copy(src.begin(), src.end(), dest.begin());

    for (const auto &i: dest) std::cout << i << ' '; // 输出:1 2 3 4 5
}

 2.2 move

        移动一个范围内的元素到另一个位置。

#include <algorithm>
#include <iostream>
#include <vector>
#include <string>

int main() {
    std::vector<std::string> src = {"one", "two", "three"};
    std::vector<std::string> dest(3);

    std::move(src.begin(), src.end(), dest.begin());

    for (const auto &str: dest) std::cout << str << ' '; // 输出:one two three
}

2.3 transform

        对范围内的每个元素应用一个函数,并将结果存储到另一个位置。

#include <algorithm>
#include <iostream>
#include <vector>

int main() {
    std::vector<int> src = {1, 2, 3, 4, 5};
    std::vector<int> dest(5);

    std::transform(src.begin(), src.end(), dest.begin(), [](int n) {
        return n * n;
    });

    for (const auto &i: dest) std::cout << i << ' '; // 输出:1 4 9 16 25
}

2.4 fill,fill_n

        用给定值填充一个范围内的元素。

#include <algorithm>
#include <iostream>
#include <vector>

int main() {
    std::vector<int> v(5);

    std::fill(v.begin(), v.end(), 10);

    for (const auto &i: v) std::cout << i << ' '; // 输出:10 10 10 10 10
}

2.5 replace,replace_if

         替换满足某个条件的所有元素。

#include <algorithm>
#include <iostream>
#include <vector>

int main() {
    std::vector<int> v = {1, 2, 3, 4, 5};

    std::replace_if(v.begin(), v.end(), [](int n) {
        return n % 2 == 0;
    }, 0);

    for (const auto &i: v) std::cout << i << ' '; // 输出:1 0 3 0 5
}

3. 删除性算法

        这类算法从容器中删除元素。`std::remove_if` 可以用来删除满足条件的所有元素。使用这些算法可以帮助我们清理数据集。

  • `std::remove`, `std::remove_if`: 删除满足某个条件的所有元素。
  • `std::unique`: 删除相邻的重复元素。

3.1 remove,remove_if

        删除满足某个条件的所有元素。

        注意,`std::remove` 和 `std::remove_if` 并不实际删除元素,而是将不满足条件的元素移动到序列的前部,并返回一个迭代器,指向最后一个不需要删除的元素的下一个位置。要完全删除元素,还需要用容器的 `erase` 方法。

#include <algorithm>
#include <iostream>
#include <vector>

int main() {
    std::vector<int> v = {1, 2, 3, 4, 5};

    auto new_end = std::remove_if(v.begin(), v.end(), [](int n) {
        return n % 2 == 0; // 删除所有偶数
    });

    v.erase(new_end, v.end());

    for (const auto &i: v) std::cout << i << ' '; // 输出:1 3 5
}

3.2 unique

        删除相邻的重复元素。

        `std::unique` 同样并不实际删除元素,而是重新排列容器中的元素,将重复元素移到容器的尾部,并返回一个迭代器,指向最后一个不重复的元素的下一个位置。为了完全删除重复元素,还需要结合容器的 `erase` 方法。

#include <algorithm>
#include <iostream>
#include <vector>

int main() {
    std::vector<int> v = {1, 1, 2, 3, 3, 3, 4, 4, 5, 5};

    auto new_end = std::unique(v.begin(), v.end());

    v.erase(new_end, v.end());

    for (const auto &i: v) std::cout << i << ' '; // 输出:1 2 3 4 5
}

4. 排序和相关算法

        排序和相关算法主要用于对数据集进行排序和查找。例如,`std::sort` 可以对一个范围内的元素进行排序,而 `std::nth_element` 可以找到第n个元素应该在的位置。这类算法在数据排序和查询时特别重要。

  • `std::sort`: 对一个范围内的元素进行排序。
  • `std::stable_sort`: 对一个范围内的元素进行稳定排序。
  • `std::partial_sort`: 对一个范围内的元素进行部分排序。
  • `std::nth_element`: 对一个范围内的元素进行部分排序,使得第n个元素位于正确的位置。

4.1 sort

        对一个范围内的元素进行排序。

#include <algorithm>
#include <iostream>
#include <vector>

int main() {
    std::vector<int> v = {5, 1, 9, 3, 7};

    std::sort(v.begin(), v.end()); // 默认升序排序

    for(const auto &i: v) std::cout << i << ' '; // 输出:1 3 5 7 9
}

4.2 stable_sort

        对一个范围内的元素进行稳定排序。

        `std::stable_sort` 和 `std::sort` 的区别在于,`std::stable_sort` 会保持相等元素的原始相对顺序。

#include <algorithm>
#include <iostream>
#include <vector>
#include <string>

int main() {
    std::vector<std::string> v = {"apple", "orange", "banana", "apple"};

    std::stable_sort(v.begin(), v.end()); 

    for(const auto &i: v) std::cout << i << ' '; // 相同元素 "apple" 的原始顺序被保持
}

4.3 partial_sort

        对一个范围内的元素进行部分排序。

        `std::partial_sort` 只确保前n个最小的元素以升序排序,其余元素位置不定。

#include <algorithm>
#include <iostream>
#include <vector>

int main() {
    std::vector<int> v = {5, 1, 9, 3, 7};

    std::partial_sort(v.begin(), v.begin() + 3, v.end()); // 前3个元素升序排序

    for(const auto &i: v) std::cout << i << ' '; // 输出可能是:1 3 5 9 7
}

4.4 nth_element

        对一个范围内的元素进行部分排序,使得第n个元素位于正确的位置。

        `std::nth_element` 确保第n个元素位于正确的位置,即它左边的元素都小于它,它右边的元素都大于它。但左右两边的元素不一定是有序的。

#include <algorithm>
#include <iostream>
#include <vector>

int main() {
    std::vector<int> v = {5, 1, 9, 3, 7};

    std::nth_element(v.begin(), v.begin() + 2, v.end()); // 保证第3个位置的元素(9)在正确的位置上

    for(const auto &i: v) std::cout << i << ' '; // 输出可能是:5 1 3 7 9 或者 1 3 5 7 9 等
}

5. 二分查找算法

        二分查找算法在有序序列中进行查找,如 `std::binary_search` 可以在有序序列中查找给定值。这类算法可以快速定位数据,提高检索效率。

  • `std::lower_bound`: 查找有序序列中第一个不小于给定值的元素。
  • `std::upper_bound`: 查找有序序列中第一个大于给定值的元素。
  • `std::binary_search`: 在有序序列中查找给定值。
  • `std::equal_range`: 在有序序列中查找等于给定值的元素的范围。

5.1 lower_bound

        查找有序序列中第一个不小于给定值的元素。

#include <algorithm>
#include <iostream>
#include <vector>

int main() {
    std::vector<int> v = {1, 2, 4, 4, 5, 6};

    auto it = std::lower_bound(v.begin(), v.end(), 4);

    if (it != v.end()) std::cout << "Lower bound of 4: " << *it; // 输出:Lower bound of 4: 4
}

5.2 upper_bound

        查找有序序列中第一个大于给定值的元素。

#include <algorithm>
#include <iostream>
#include <vector>

int main() {
    std::vector<int> v = {1, 2, 4, 4, 5, 6};

    auto it = std::upper_bound(v.begin(), v.end(), 4);

    if (it != v.end()) std::cout << "Upper bound of 4: " << *it; // 输出:Upper bound of 4: 5
}

5.3 binary_search

        在有序序列中查找给定值。

#include <algorithm>
#include <iostream>
#include <vector>

int main() {
    std::vector<int> v = {1, 2, 3, 4, 5};

    if (std::binary_search(v.begin(), v.end(), 3)) {
        std::cout << "3 is found in the vector"; // 输出:3 is found in the vector
    } else {
        std::cout << "3 is not found in the vector";
    }
}

5.4 equal_range

        在有序序列中查找等于给定值的元素的范围。

#include <algorithm>
#include <iostream>
#include <vector>

int main() {
    std::vector<int> v = {1, 2, 4, 4, 5, 6};

    auto range = std::equal_range(v.begin(), v.end(), 4);
    auto first = range.first;
    auto last = range.second;

    std::cout << "The equal range of 4: ";
    for (auto it = first; it != last; ++it) std::cout << *it << ' '; // 输出:The equal range of 4: 4 4
}

6. 堆算法

        堆算法用于操作堆,例如,`std::make_heap` 可以将一个序列转换为一个堆。这类算法在优先队列和调度算法中广泛使用。

  • `std::make_heap`: 转换一个序列为堆。
  • `std::push_heap`: 向堆中插入一个元素。
  • `std::pop_heap`: 从堆中删除最大的元素。

6.1 make_heap

        转换一个序列为堆。

#include <algorithm>
#include <iostream>
#include <vector>

int main() {
    std::vector<int> v = {3, 1, 4, 1, 5, 9, 2};

    std::make_heap(v.begin(), v.end());

    std::cout << "Max element (heap top): " << v.front(); // 输出:Max element (heap top): 9
}

6.2 push_heap

        向堆中插入一个元素。

        向堆中插入元素时,元素应该首先被添加到容器的末尾,然后调用 `std::push_heap`。

#include <algorithm>
#include <iostream>
#include <vector>

int main() {
    std::vector<int> v = {9, 5, 4, 1, 1};

    v.push_back(10); // 先将10添加到向量的末尾
    std::push_heap(v.begin(), v.end()); // 然后将10添加到堆中

    std::cout << "Max element (heap top): " << v.front(); // 输出:Max element (heap top): 10
}

6.3 pop_heap

        从堆中删除最大的元素。

        要从堆中删除元素,应该首先调用 `std::pop_heap`,这会将最大元素(堆顶元素)与容器的最后一个元素交换,然后从容器中删除最后一个元素。

#include <algorithm>
#include <iostream>
#include <vector>

int main() {
    std::vector<int> v = {9, 5, 4, 1, 1};

    std::pop_heap(v.begin(), v.end()); // 9 和 1 交换位置
    int max_element = v.back(); // 获取(原来的)堆顶元素
    v.pop_back(); // 从容器中删除(原来的)堆顶元素

    std::cout << "Popped element: " << max_element << '\n'; // 输出:Popped element: 9
    std::cout << "New max element (heap top): " << v.front(); // 输出:New max element (heap top): 5
}

7. 最大和最小元素算法

        这类算法用于查找范围内的最大或最小元素。例如,`std::max_element` 可以找到容器中的最大元素。这些算法在数据分析中非常有用。

  • `std::max`, `std::min`: 返回两个元素中的最大值或最小值。
  • `std::max_element`, `std::min_element`: 在一个范围内查找最大或最小的元素。
  • `std::minmax`, `std::minmax_element`: 在一个范围内同时查找最大和最小的元素。

7.1 max,min

        返回两个元素中的最大值或最小值。

#include <algorithm>
#include <iostream>

int main() {
    std::cout << "Max: " << std::max(3, 5) << '\n'; // 输出:Max: 5
    std::cout << "Min: " << std::min(3, 5) << '\n'; // 输出:Min: 3
}

7.2 max_element,min_element

        在一个范围内查找最大或最小的元素。

#include <algorithm>
#include <iostream>
#include <vector>

int main() {
    std::vector<int> v = {3, 1, 4, 1, 5, 9, 2};

    auto max_it = std::max_element(v.begin(), v.end());
    auto min_it = std::min_element(v.begin(), v.end());

    std::cout << "Max Element: " << *max_it << '\n'; // 输出:Max Element: 9
    std::cout << "Min Element: " << *min_it << '\n'; // 输出:Min Element: 1
}

7.3 minmax,minmax_element

        在一个范围内同时查找最大和最小的元素。

#include <algorithm>
#include <iostream>
#include <vector>

int main() {
    std::vector<int> v = {3, 1, 4, 1, 5, 9, 2};

    auto minmax_it = std::minmax_element(v.begin(), v.end());
    auto minmax_val = std::minmax({3, 1, 4, 1, 5, 9, 2}); // initializer_list

    std::cout << "Max Element: " << *minmax_it.second << " Min Element: " << *minmax_it.first << '\n'; // 输出:Max Element: 9 Min Element: 1
    std::cout << "Max Value: " << minmax_val.second << " Min Value: " << minmax_val.first << '\n'; // 输出:Max Value: 9 Min Value: 1
}

8. 数值算法

        数值算法主要用于进行数值计算。例如,`std::accumulate` 可以计算一个范围内的元素的和或其他二元操作的累积结果,非常适用于统计学和数据分析。

  • `std::iota`: 生成一个递增的序列。
  • `std::accumulate`: 计算一个范围内的元素的和或其他二元操作的累积结果。
  • `std::inner_product`: 计算两个序列的内积。
  • `std::adjacent_difference`: 计算相邻元素的差值。
  • `std::partial_sum`: 计算部分和。

8.1 iota

        生成一个递增的序列。

#include <numeric>
#include <vector>
#include <iostream>

int main() {
    std::vector<int> v(5);
    std::iota(v.begin(), v.end(), 1); // 生成:1 2 3 4 5
    
    for (const auto& i: v) std::cout << i << ' '; // 输出:1 2 3 4 5
}

8.2 accumulate

        计算一个范围内的元素的和或其他二元操作的累积结果。

#include <numeric>
#include <vector>
#include <iostream>

int main() {
    std::vector<int> v = {1, 2, 3, 4, 5};

    int sum = std::accumulate(v.begin(), v.end(), 0); // 计算和
    
    std::cout << "Sum: " << sum; // 输出:Sum: 15
}

8.3 inner_product

        计算两个序列的内积。

#include <numeric>
#include <vector>
#include <iostream>

int main() {
    std::vector<int> v1 = {1, 2, 3, 4};
    std::vector<int> v2 = {5, 6, 7, 8};

    int product = std::inner_product(v1.begin(), v1.end(), v2.begin(), 0);
    
    std::cout << "Inner Product: " << product; // 输出:Inner Product: 70
}

8.4 adjacent_difference

        计算相邻元素的差值。`

#include <numeric>
#include <vector>
#include <iostream>

int main() {
    std::vector<int> v = {1, 2, 4, 7, 11};
    std::vector<int> result(v.size());

    std::adjacent_difference(v.begin(), v.end(), result.begin());
    
    for (const auto& i: result) std::cout << i << ' '; // 输出:1 1 2 3 4
}

8.5 partial_sum

        计算部分和。

#include <numeric>
#include <vector>
#include <iostream>

int main() {
    std::vector<int> v = {1, 2, 3, 4, 5};
    std::vector<int> result(v.size());

    std::partial_sum(v.begin(), v.end(), result.begin());
    
    for (const auto& i: result) std::cout << i << ' '; // 输出:1 3 6 10 15
}

总结:

        C++的STL算法提供了一套强大且多样化的工具集,能够帮助开发者有效地处理各种问题。通过结合使用这些算法,我们可以更容易地实现复杂功能,同时保持代码的清晰和高效。在实际开发中,掌握并熟练运用这些算法会极大地提高我们的编程效率和代码质量。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

SecureCode

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值