STL算法

STL算法

STL算法由头文件<algorithm>, <numeric><functional> 组成的。

其中**<algorithm>**:这是STL中最大的头文件,包括了各种常用算法,如:比较,交换,查找,遍历,复制,修改,排序等相关操作。

<numeric>这个头文件相对较小,他主要包括了序列上进行数学运算法的模板函数。如:累积,内积,部分和,相邻差异等。

<functional>这个头文件定义了一些模板类,用于声明函数对象(也称为仿函数)。这些函数对象经常用于STL算法中,特别是那些需要自定义比较或操作的算法。如:比较,逻辑操作等。

常用遍历算法

for_each

for_each它允许将给定函数或可调用对象应用于范围中的每个函数。也就是说它会遍历集合中每一个元素,然后执行你需要的操作。

for_each的函数模板

template<class InputIt, class UnaryFunction>
unaryFuction for_each(InputIt first, InputIt last, UnaryFunction f);

InputIt: 元素范围开头和结尾的输入迭代器类型。

UnaryFunction: 一元函数的类型。

返回值是函数将可调用对象f应用到范围中的每个元素后返回。

我将介绍一下for_each的基本实现

template<typename Iterator, typename Func>
void My_for_each(Iterator begin, Iterator end, Func f){
    while(begin != end){
        f(*begin);
        ++begin;
    }
}

下面是用My_for_each调用函数的操作。

#include<iostream>
#include<vector>

using namespace std;

template<typename Iterator, typename Func>
void My_for_each(Iterator begin, Iterator end, Func f){
    while(begin != end){
        f(*begin);
        ++begin;
    }
}

class PrintDouble{
public:
    void operator()(int i) const{
        cout<< i * 2<<" ";
    }
};

int main(){
    vector<int> number = {1,2,3,4,5};
    My_for_each(number.begin(), number.end(),[](int n){
        cout<< n <<" ";
    });

    cout<<endl;
    
    My_for_each(number.begin(), number.end(), PrintDouble());

    return 0;
}

Note:

One interesting thing to note about for_each is that the function or callable can have side effects. Meaning , they can change the state of objects outside of their own scope.

Beside,the returned function object (f) can be used after the for_each call, especially if it maintains a state. For example, if you want to count occurrences of a certain condition, the callable object can keep a counter which will be available after the execution of for_each.

transform

transformfor_each的算法操作类似,它是对给定范围内的每个元素应用指定操作,并且将结果储存在另一个范围中。

transform的函数模板如下,

template<class InputIterator, class OutputIterator, class UnaryOperation>
OutputIterator transform(InputIterator first1, InputIterator last1, OutputIterator result, UnaryOperation op){
    while(first1 != last1){
        *result = op(*first1);
        ++result;
        ++first1;
    }
    return result;
}

其中result是一个迭代器,指向存储转换后的值的目标范围的开头。

下面是一个简单示例:

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

using namespace std;

int main() {
    vector<int> input = {1, 2, 3, 4, 5};
    vector<int> output(input.size());

    // Use std::transform to double each element in input and store in output
    transform(input.begin(), input.end(), output.begin(), [](int x) {
        return x * 2;
    });

    // Print the transformed values in output
    for (int val : output) {
        cout << val << " ";
    }

    return 0;
}

常用查找算法

find

在给定的范围内查找指定的元素。如果找到,返回指定第一个匹配元素的迭代器;否则返回范围的末尾。

vector<int> v = {1, 2, 3, 4, 5};
auto it = find(v.begin(), v.end(), 3);
if (it != v.end()) {
    cout << "Found the value: " << *it << endl;
} else {
    cout << "Value not found." << endl;
}

find_if

在给定的范围内查找满足特定条件的第一个元素。

vector<int> v = {1, 2, 3, 4, 5};
auto it = find_if(v.begin(), v.end(), [](int x){ return x > 3; });
if (it != v.end()) {
    cout << "First value greater than 3: " << *it << endl;
} else {
    cout << "No values found greater than 3." << endl;
}

adjacent_find

在给定的范围内查找第一对相邻的匹配元素。

vector<int> v = {1, 2, 3, 3, 4};
auto it = adjacent_find(v.begin(), v.end());
if (it != v.end()) {
    cout << "Found adjacent value: " << *it << endl;
} else {
    cout << "No adjacent matching values found." << endl;
}

binary_search

在一个排序的范围内使用二分查找法检查一个元素是否存在。返回一个bool值,表示元素是否存在。

vector<int> v = {1, 2, 3, 4, 5};
if (binary_search(v.begin(), v.end(), 3)) {
    cout << "Value 3 exists." << endl;
} else {
    cout << "Value 3 does not exist." << endl;
}

count

在给定的范围内统计指定元素的出现次数

vector<int> v = {1, 2, 3, 4, 5, 3};
int num = count(v.begin(), v.end(), 3);
cout << "Number 3 appears " << num << " times." << endl;

count_if

在给定的范围内统计满足特定条件的元素的数量

int num = count_if(v.begin(), v.end(), [](int x){ return x > 3; });
cout << "Number of values greater than 3: " << num << endl;

常用排序算法

sort

对给定范围内的元素进行排序。

默认按升序排序。如果想要降序或者其他类型排序,可以提供自定义的比较函数

 vector<int> v = {4,5,8,55,7,2,1,9};
    sort(v.begin(), v.end());
    for_each(v.begin(), v.end(), [](int x){cout << x << " ";});
    cout << endl;
    // 降序
    sort(v.begin(), v.end(), [](int x, int y){return x > y;});
    for_each(v.begin(), v.end(), [](int x){cout << x << " ";});

random_shuffle

对给定范围的元素进行随机重新排列。(在c++17中这个函数已经被shuffle取代。)

#include <algorithm>
#include <vector>
#include <ctime>
#include <cstdlib>
using namespace std;

vector<int> v = {1, 2, 3, 4, 5};
srand(time(nullptr));  // 设置随机数种子
random_shuffle(v.begin(), v.end());
for (int i : v) {
    cout << i << " ";
} // 输出可能为: 3 5 1 4 2

merge

合并两个已排序的范围,并存储到另一个容器内。

#include <algorithm>
#include <vector>
using namespace std;

vector<int> a = {1, 3, 5};
vector<int> b = {2, 4, 6};
vector<int> result(a.size() + b.size());

merge(a.begin(), a.end(), b.begin(), b.end(), result.begin());
for (int i : result) {
    cout << i << " ";
} // 输出: 1 2 3 4 5 6

reverse

反转给定范围的元素。

vector<int> v = {1, 2, 3, 4, 5};
reverse(v.begin(), v.end());
for (int i : v) {
    cout << i << " ";
} // 输出: 5 4 3 2 1

常用拷贝和替换函数

copy

将一个容器内的指定范围的元素拷贝到另一个容器中。

vector<int> source = {1, 2, 3, 4, 5};
vector<int> destination(source.size());

copy(source.begin(), source.end(), destination.begin());
for (int i : destination) {
    cout << i << " ";
} // 输出: 1 2 3 4 5

replace

将容器内指定范围的旧元素替换为新元素。

vector<int> v = {1, 2, 3, 4, 3};
replace(v.begin(), v.end(), 3, 99);
for (int i : v) {
    cout << i << " ";
} // 输出: 1 2 99 4 99

replace_if

将容器内指定范围满足条件的元素替换为新元素。

vector<int> v = {1, 2, 3, 4, 5};
replace_if(v.begin(), v.end(), [](int n) { return n > 3; }, 99);
for (int i : v) {
    cout << i << " ";
} // 输出: 1 2 3 99 99

swap

交换两个容器(或两个元素)的内容。

vector<int> a = {1, 2, 3};
vector<int> b = {4, 5, 6};

swap(a, b);
for (int i : a) {
    cout << i << " ";
} // 输出: 4 5 6

for (int i : b) {
    cout << i << " ";
} // 输出: 1 2 3

常用算法生成算法

accumulate

计算给定范围内元素的累计总和

函数原型:accumulate(iterator beg, iterator end, value);

其中value是起始值

#include <numeric>
#include <vector>
using namespace std;

vector<int> v = {1, 2, 3, 4, 5};
int sum = accumulate(v.begin(), v.end(), 0);
cout << sum; // 输出: 15

备注: accumulate也可以用来进行其他二元操作,例如累乘,但这需要提供一个自定义的二元函数。

fill

为容器内指定范围的所有元素设置一个新的值。

#include <algorithm>
#include <vector>
using namespace std;

vector<int> v(5);  // 创建一个大小为5的vector,所有元素默认初始化为0
fill(v.begin(), v.end(), 42);
for (int i : v) {
    cout << i << " ";
} // 输出: 42 42 42 42 42

备注: 虽然fill被定义在<algorithm>中,但是与accumulate一样,它也可以被看作是一个算术生成算法。

常用集合算法

set_intersection

求两个已排序的范围的交集。

函数原形:

template <class InputIterator1, class InputIterator2, class OutputIterator>
OutputIterator set_intersection(InputIterator1 first1, InputIterator1 last1,
                                InputIterator2 first2, InputIterator2 last2,
                                OutputIterator result);

result是目标容器的开始迭代器

#include <algorithm>
#include <vector>
using namespace std;

vector<int> a = {1, 2, 3, 4, 5};
vector<int> b = {4, 5, 6, 7, 8};
vector<int> intersection;

set_intersection(a.begin(), a.end(), b.begin(), b.end(), back_inserter(intersection));

for (int i : intersection) {
    cout << i << " ";
} // 输出: 4 5

注意: 输入范围必须是已排序的。输出不会自动删除重复元素。

set_union

求两个已排序的范围的并集。

vector<int> a = {1, 2, 3, 4};
vector<int> b = {3, 4, 5, 6};
vector<int> union_result;

set_union(a.begin(), a.end(), b.begin(), b.end(), back_inserter(union_result));

for (int i : union_result) {
    cout << i << " ";
} // 输出: 1 2 3 4 5 6

set_difference

求两个已排序的范围的差集(即第一个范围中存在但第二个范围中不存在的元素)。

vector<int> a = {1, 2, 3, 4, 5};
vector<int> b = {4, 5, 6, 7, 8};
vector<int> difference;

set_difference(a.begin(), a.end(), b.begin(), b.end(), back_inserter(difference));

for (int i : difference) {
    cout << i << " ";
} // 输出: 1 2 3
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Tian Meng

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

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

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

打赏作者

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

抵扣说明:

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

余额充值