五、STL之常用算法

一、算法概述

算法主要是由头文件<algorithm> <functional> <numeric>组成。
<algorithm>是所有STL头文件中最大的一个,其中常用的功能涉及到比较,交换,查找,遍历,复制,修改,反转,排序,合并等...
<numeric>体积很小,只包括在几个序列容器上进行的简单运算的模板函数.
<functional> 定义了一些模板类,用以声明函数对象。

二、常用遍历算法

2.1 for_each

/*
    for_each(iterator beg, iterator end, _callback);
    @param beg 开始迭代器
    @param end 结束迭代器
    @param _callback  函数回调或者函数对象
    @return 函数对象
*/

/*
    1. for_each 调用回调函数
    2. for_each 调用仿函数
    3. for_each 有返回值
    4. for_each 可以绑定参数进行输出
*/

#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
#include<string>
#include<vector>
#include<algorithm>
#include<functional>
using namespace std;

void myPrint(int val)
{
    cout << val << " ";
}

class Print
{
public:
    void operator()(int val)
    {
        cout << val << " ";
        this->count++;
    }
    int count = 0;
};

class Print02:public binary_function<int, int, void>
{
public:
    void operator()(int val, int start)const
    {
        cout << val + start << " ";
    }
};

void test()
{
    vector<int> v;
    for (int i = 0; i < 5; i++)
    {
        v.push_back(i);
    }
    // 1. for_each 调用回调函数
    for_each(v.begin(), v.end(), myPrint);  // 0 1 2 3 4 
    cout << endl;
    
    // 2. for_each 调用仿函数
    for_each(v.begin(), v.end(), Print());  // 0 1 2 3 4
    cout << endl;

    // 3. for_each 有返回值
    Print mp = for_each(v.begin(), v.end(), Print());  // 返回值是Print类型
    cout << endl;
    cout << "count = " << mp.count << endl;   // count = 5

    // 4. for_each 可以绑定参数进行输出
    for_each(v.begin(), v.end(), bind2nd(Print02(), 100));
    cout << endl;

}

int main()
{
    test();
    return EXIT_SUCCESS;
}

2.2 transform

/*
    transform(iterator beg1, iterator end1, iterator beg2, _callbakc);
    transform算法 将指定容器区间元素搬运到另一容器中
    注意 : transform 不会给目标容器分配内存,所以需要我们提前分配好内存
    @param beg1 源容器开始迭代器
    @param end1 源容器结束迭代器
    @param beg2 目标容器开始迭代器
    @param _cakkback 回调函数或者函数对象
    @return 返回目标容器迭代器
*/

#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
#include<string>
#include<vector>
#include<algorithm>
#include<functional>
using namespace std;

class MyTransform
{
public:
    int operator()(int val)
    {
        return val;
    }
};

void test()
{
    vector<int> v;
    for (int i = 0; i < 5; i++)
    {
        v.push_back(i);
    }
    vector<int> vTarget;
    // 需要重新制定 vTarget的大小
    vTarget.resize(v.size());
    transform(v.begin(), v.end(), vTarget.begin(), MyTransform());
    for_each(vTarget.begin(), vTarget.end(), [](int val){cout << val << " "; });
    cout << endl;
}


int main()
{
    test();
    return EXIT_SUCCESS;
}

三、常用查找算法

3.1 find

/*
    find(iterator beg, iterator end, value);
    find算法 查找元素
    @param beg 容器开始迭代器
    @param end 容器结束迭代器
    @param value 查找的元素
    @return 返回查找元素的位置
*/
/*
    1. 查找系统存在的数据类型
    2. 查找自定义数据类型, 需要重载 ==
*/

#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
#include<string>
#include<vector>
#include<algorithm>
#include<functional>
using namespace std;

class Person
{
public:
    Person(string name, int age)
    {
        this->Name = name;
        this->Age = age;
    }
    bool operator==(const Person &p)
    {
        if ((this->Name == p.Name) && (this->Age == p.Age))
        {
            return true;
        }
        return false;
    }
    string Name;
    int Age;
};

void test()
{
    vector<int> v1;
    for (int i = 0; i < 5; i++)
    {
        v1.push_back(i);
    }

    // 1. 查找系统存在的数据类型
    // 查找有没有 3 这个元素, 返回值是迭代器
    vector<int>::iterator it = find(v1.begin(), v1.end(), 3);
    if (it != v1.end())
    {
        cout << "找到了元素: " << *it << endl; // 找到了元素: 3
    }
    else
    {
        cout << "没找到!" << endl;
    }

    // 2. 查找自定义数据类型
    vector<Person> v2;
    Person p1("aaa", 10);
    Person p2("bbb", 20);
    Person p3("ccc", 30);
    Person p4("ddd", 40);
    v2.push_back(p1);
    v2.push_back(p2);
    v2.push_back(p3);
    v2.push_back(p4);
    vector<Person>::iterator Pit = find(v2.begin(), v2.end(), p3); // 直接这样是不行的,系统不知道查找逻辑,查看错误源码, 是不知道如何比较==, 所以需要重载 == 
    if (Pit != v2.end())
    {
        cout << "找到了, 姓名: " << Pit->Name << "  年龄: " << Pit->Age << endl;
    }
    else
    {
        cout << "没找到!" << endl;
    }
}

int main()
{
    test();
    return EXIT_SUCCESS;
}

3.2 find_if

/*
    find_if(iterator beg, iterator end, _callback);
    find_if算法 条件查找
    @param beg 容器开始迭代器
    @param end 容器结束迭代器
    @param  callback 回调函数或者谓词(返回bool类型的函数对象)
    @return bool 查找返回true 否则false
*/

#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
#include<string>
#include<vector>
#include<algorithm>
#include<functional>
using namespace std;

class Person
{
public:
    Person(string name, int age)
    {
        this->Name = name;
        this->Age = age;
    }
    string Name;
    int Age;
};

class MyComparePerson : public binary_function<Person*, Person *,  bool>
{
public:
    bool operator()(Person * p1, Person * p2) const
    {
        if(p1->Name == p2->Name  && p1->Age == p2->Age)
        {
            return true;
        }
        return false;
    }
};

void test()
{
    vector<Person *> v1;
    Person p1("aaa", 10);
    Person p2("bbb", 20);
    Person p3("ccc", 30);
    Person p4("ddd", 40);
    v1.push_back(&p1);
    v1.push_back(&p2);
    v1.push_back(&p3);
    v1.push_back(&p4);

    Person *p = new Person("bbb", 20);
    find(v1.begin(), v1.end(), p);   // 语法不会报错, 因为 p是指针, 指针可以进行比较,虽然没有意义,但是是可以的,需要的是指针指向的值
    // 可以采用按照条件的方式来查找
    vector<Person*>::iterator it = find_if(v1.begin(), v1.end(), bind2nd(MyComparePerson(), p));
    if (it != v1.end())
    {
        cout << "找到了:  姓名:  " << (*it)->Name << "  年龄: " << (*it)->Age << endl;
    }
    else
    {
        cout << "没找到!" << endl;
    }
}

int main()
{
    test();
    return EXIT_SUCCESS;
}

3.3 adjacent_find

/*
    adjacent_find(iterator beg, iterator end, _callback);
    adjacent_find算法 查找相邻重复元素
    @param beg 容器开始迭代器
    @param end 容器结束迭代器
    @param  _callback 回调函数或者谓词(返回bool类型的函数对象)
    @return 返回相邻元素的第一个位置的迭代器
*/

#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
#include<string>
#include<vector>
#include<algorithm>
using namespace std;

class Person
{
public:
    Person(string name, int age)
    {
        this->Name = name;
        this->Age = age;
    }
    string Name;
    int Age;
};

void test()
{
    // 返回重复的并且是相邻的元素
    vector<int> v;
    v.push_back(1);
    v.push_back(3);
    v.push_back(1);
    v.push_back(2);
    v.push_back(2);
    v.push_back(5);
    v.push_back(4);
    
    vector<int>::iterator it = adjacent_find(v.begin(), v.end());
    if (it != v.end())
    {
        cout << "找到了:   " << *it << endl; // 找到了:   2
    }
    else
    {
        cout << "没找到" << endl;
    }
}

int main()
{
    test();
    return EXIT_SUCCESS;
}

3.4 binary_search

/*
    bool binary_search(iterator beg, iterator end, value);
    binary_search算法 二分查找法
    注意: 在无序序列中不可用
    @param beg 容器开始迭代器
    @param end 容器结束迭代器
    @param value 查找的元素
    @return bool 查找返回true 否则false
*/

#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
#include<string>
#include<vector>
#include<algorithm>
#include<functional>
using namespace std;

void test()
{
    // 返回重复的并且是相邻的元素
    vector<int> v;
    v.push_back(1);
    v.push_back(2);
    v.push_back(3);
    v.push_back(4);
    v.push_back(6);
    v.push_back(8);
    v.push_back(9);
    bool ret = binary_search(v.begin(), v.end(), 4);
    if (ret)
    {
        cout << "找到了" << endl;
    }
    else
    {
        cout << "没找到" << endl;
    }
}

int main()
{
    test();
    return EXIT_SUCCESS;
}

3.5 count

/*
    count(iterator beg, iterator end, value);
    count算法 统计元素出现次数, 按值进行统计
    @param beg 容器开始迭代器
    @param end 容器结束迭代器
    @param  value回调函数或者谓词(返回bool类型的函数对象)
    @return int返回元素个数
*/

#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
#include<string>
#include<vector>
#include<algorithm>
using namespace std;

void test()
{
    vector<int> v;
    for (int i = 0; i < 5; i++)
    {
        v.push_back(i);
    }
    v.push_back(3);
    // 按值进行统计
    int num = count(v.begin(), v.end(), 3);
    cout << "num = " << num << endl;  // num = 2

}

int main()
{
    test();
    return EXIT_SUCCESS;
}

3.7 count_if

/*
    count_if(iterator beg, iterator end, _callback);
    count算法 统计元素出现次数  按条件进行统计
    @param beg 容器开始迭代器
    @param end 容器结束迭代器
    @param  callback 回调函数或者谓词(返回bool类型的函数对象)
    @return int返回元素个数
*/

#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
#include<string>
#include<vector>
#include<algorithm>
#include<functional>
using namespace std;

class MyCompare
{
public:
    bool operator()(int val)
    {
        return val > 3;
    }
};

void test()
{
    vector<int> v;
    for (int i = 0; i < 5; i++)
    {
        v.push_back(i);
    }
    v.push_back(4);
    // 按条件进行统计, 统计大于3的个数
    int num = count_if(v.begin(), v.end(), MyCompare());
    cout << "大于3的个数: " << num << endl;  // num = 2
}

int main()
{
    test();
    return EXIT_SUCCESS;
}

四、常用排序算法

4.1 merge

/*
    merge(iterator beg1, iterator end1, iterator beg2, iterator end2, iterator dest)
    merge算法 容器元素合并,并存储到另一容器中  两个容器必须是有序的
    @param beg1 容器1开始迭代器
    @param end1 容器1结束迭代器
    @param beg2 容器2开始迭代器
    @param end2 容器2结束迭代器
    @param dest  目标容器开始迭代器
*/

#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
#include<string>
#include<vector>
#include<algorithm>
#include<functional>
using namespace std;

void test()
{
    vector<int> v1;
    for (int i = 0; i < 5; i++)
    {
        v1.push_back(i);
    }
    vector<int> v2;
    for (int i = 0; i < 5; i++)
    {
        v2.push_back(i + 5);
    }
    // 目标容器
    vector<int> vTarget;
    // 扩容目标容器
    vTarget.resize(v1.size() + v2.size());
    merge(v1.begin(), v1.end(), v2.begin(), v2.end(), vTarget.begin());
    for_each(vTarget.begin(), vTarget.end(), [](int val){cout << val << " "; });  // 0 1 2 3 4 5 6 7 8 9
    cout << endl;
}


int main()
{
    test();
    return EXIT_SUCCESS;
}

 

4.2 sort

/*
    sort(iterator beg, iterator end, _callback)
    sort算法 容器元素排序
    注意:两个容器必须是有序的
    @param beg 容器1开始迭代器
    @param end 容器1结束迭代器
    @param _callback 回调函数或者谓词(返回bool类型的函数对象)
*/
#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
#include<string>
#include<vector>
#include<algorithm>
#include<functional>
using namespace std;

void test()
{
    vector<int> v1;
    for (int i = 0; i < 5; i++)
    {
        v1.push_back(i);
    }
    // 从大到小排序
    sort(v1.begin(), v1.end(), greater<int>());
    for_each(v1.begin(), v1.end(), [](int val){cout << val << " "; });  // 4 3 2 1 0
    cout << endl;
}


int main()
{
    test();
    return EXIT_SUCCESS;
}

4.3 random_shuffle

/*
    random_shuffle(iterator beg, iterator end);
    sort算法 对指定范围内的元素随机调整次序,  洗牌
    @param beg 容器开始迭代器
    @param end 容器结束迭代器
*/
#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
#include<string>
#include<vector>
#include<algorithm>
#include<functional>
#include<ctime>
using namespace std;

void test()
{
    srand((unsigned int) time(NULL));
    vector<int> v1;
    for (int i = 0; i < 5; i++)
    {
        v1.push_back(i);
    }
    random_shuffle(v1.begin(), v1.end());
    for_each(v1.begin(), v1.end(), [](int val){cout << val << " "; }); // 0 2 1 4 3
}


int main()
{
    test();
    return EXIT_SUCCESS;
}

4.4 reverse

/*
    reverse(iterator beg, iterator end)
    reverse算法 反转指定范围的元素
    @param beg 容器开始迭代器
    @param end 容器结束迭代器
*/
#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
#include<string>
#include<vector>
#include<algorithm>
#include<functional>
using namespace std;

void test()
{
    
    vector<int> v1;
    for (int i = 0; i < 5; i++)
    {
        v1.push_back(i);
    }
    v1.push_back(3);
    reverse(v1.begin(), v1.end());
    for_each(v1.begin(), v1.end(), [](int val){cout << val << " "; }); // 3 4 3 2 1 0
}


int main()
{
    test();
    return EXIT_SUCCESS;
}

五、常用拷贝和替换算法

5.1 copy

/*
    copy(iterator beg, iterator end, iterator dest)
    copy算法 将容器内指定范围的元素拷贝到另一容器中
    @param beg 容器开始迭代器
    @param end 容器结束迭代器
    @param dest 目标起始迭代器
*/

#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
#include<string>
#include<vector>
#include<algorithm>
using namespace std;

void test()
{
    vector<int> v1;
    for (int i = 0; i < 5; i++)
    {
        v1.push_back(i);
    }
    vector<int> v2;
    v2.resize(v1.size());
    copy(v1.begin(), v1.end(), v2.begin());
    for_each(v2.begin(), v2.end(), [](int val){cout << val << " "; });  // 0 1 2 3 4
}


int main()
{
    test();
    return EXIT_SUCCESS;
}

5.2 replace

/*
    replace(iterator beg, iterator end, oldvalue, newvalue);
    replace算法 将容器内指定范围的旧元素修改为新元素
    @param beg 容器开始迭代器
    @param end 容器结束迭代器
    @param oldvalue 旧元素
    @param oldvalue 新元素
*/

#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
#include<string>
#include<vector>
#include<algorithm>
#include<iterator>
using namespace std;

void test()
{
    vector<int> v1;
    for (int i = 0; i < 5; i++)
    {
        v1.push_back(i);
    }
    v1.push_back(2);
    replace(v1.begin(), v1.end(), 2, 300);
    for_each(v1.begin(), v1.end(), [](int val){cout << val << " "; });  // 0 1 300 3 4 300
    // 还可以用下面的方式输出
    cout << endl;
    copy(v1.begin(), v1.end(), ostream_iterator<int>(cout, " "));  // 0 1 300 3 4 300
}


int main()
{
    test();
    return EXIT_SUCCESS;
}

5.3 replace_if

/*
    replace_if(iterator beg, iterator end, _callback, newvalue);
    replace_if算法 将容器内指定范围满足条件的元素替换为新元素
    @param beg 容器开始迭代器
    @param end 容器结束迭代器
    @param callback函数回调或者谓词(返回Bool类型的函数对象)
    @param oldvalue 新元素
*/
#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
#include<string>
#include<vector>
#include<algorithm>
#include<iterator>
using namespace std;

class MyCompare
{
public:
    bool operator()(int val)
    {
        return val > 3;
    }
};


void test()
{
    vector<int> v1;
    for (int i = 0; i < 5; i++)
    {
        v1.push_back(i);
    }
    v1.push_back(2);
    // 按条件替换, 将所有大于3的都替换成300
    replace_if(v1.begin(), v1.end(), MyCompare(), 3000);
    for_each(v1.begin(), v1.end(), [](int val){cout << val << " "; });  // 0 1 2 3 3000 2
    // 还可以用下面的方式输出
    cout << endl;
    copy(v1.begin(), v1.end(), ostream_iterator<int>(cout, " "));   // 0 1 2 3 3000 2
}


int main()
{
    test();
    return EXIT_SUCCESS;
}

5.4 swap

/*
    swap(container c1, container c2);
    swap算法 互换两个容器的元素
    @param c1容器1
    @param c2容器2
*/
#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
#include<string>
#include<vector>
#include<algorithm>
#include<iterator>
using namespace std;

class MyCompare
{
public:
    bool operator()(int val)
    {
        return val > 3;
    }
};


void test()
{
    vector<int> v1;
    for (int i = 0; i < 5; i++)
    {
        v1.push_back(i);
    }
    v1.push_back(2);
    vector<int> v2;
    for (int i = 0; i < 8; i++)
    {
        v2.push_back(i + 10);
    }
    swap(v1, v2);
    // 按条件替换, 将所有大于3的都替换成300
    for_each(v1.begin(), v1.end(), [](int val){cout << val << " "; });  // 10 11 12 13 14 15 16 17
    cout << endl;
    for_each(v2.begin(), v2.end(), [](int val){cout << val << " "; });  // 0 1 2 3 4 2
    // 还可以用下面的方式输出
    cout << endl;
    copy(v1.begin(), v1.end(), ostream_iterator<int>(cout, " "));   //10 11 12 13 14 15 16 17
}


int main()
{
    test();
    return EXIT_SUCCESS;
}

六、常用算数生成算法

6.1 accumulate

/*
    accumulate(iterator beg, iterator end, value);
    accumulate算法 计算容器元素累计总和
    @param beg 容器开始迭代器
    @param end 容器结束迭代器
    @param value 起始的累加值
*/

#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
#include<string>
#include<vector>
#include<numeric>
#include<iterator>
using namespace std;


void test()
{
    vector<int> v;
    for (int i = 0; i <= 100; i++)
    {
        v.push_back(i);
    }
    // 头文件 numeric
    int num = accumulate(v.begin(), v.end(), 0); // 第三个参数是起始的累加值
    cout << "num = " << num << endl;           // num = 5050
}

int main()
{
    test();
    return EXIT_SUCCESS;
}

6.2 fill

/*
    fill(iterator beg, iterator end, value)
    fill算法 向容器中添加元素
    @param beg 容器开始迭代器
    @param end 容器结束迭代器
    @param value 填充元素
*/

#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
#include<string>
#include<vector>
#include<numeric>
#include<iterator>
using namespace std;

void test()
{
    vector<int> v;
    v.resize(5);
    fill(v.begin(), v.end(), 500);
    copy(v.begin(), v.end(), ostream_iterator<int>(cout, " ")); // 500 500 500 500 500
}

int main()
{
    test();
    return EXIT_SUCCESS;
}

七、常用集合算法

#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
#include<string>
#include<vector>
#include<algorithm>
#include<iterator>
using namespace std;


void test()
{
    vector<int> v1;
    vector<int> v2;
    for (int i = 0; i < 5; i++)
    {
        v1.push_back(i);
        v2.push_back(i + 3);
    }


    /*
        交集
        set_intersection(iterator beg1, iterator end1, iterator beg2, iterator end2, iterator dest);
        set_intersection算法 求两个set集合的交集
        注意:两个集合必须是有序序列
        @param beg1 容器1开始迭代器
        @param end1 容器1结束迭代器
        @param beg2 容器2开始迭代器
        @param end2 容器2结束迭代器
        @param dest  目标容器开始迭代器
        @return 目标容器的最后一个元素的迭代器地址
    */
    vector<int> vTarget;  // 目标容器
    vTarget.resize(min(v1.size() ,v2.size()));  // 两个容器中取小的。
    vector<int>::iterator itEnd = set_intersection(v1.begin(), v1.end(), v2.begin(), v2.end(), vTarget.begin());
    copy(vTarget.begin(), itEnd, ostream_iterator<int>(cout, " "));   // 3, 4
    cout << endl;

    /*
        并集
        set_union(iterator beg1, iterator end1, iterator beg2, iterator end2, iterator dest);
        set_union算法 求两个set集合的并集
        注意:两个集合必须是有序序列
        @param beg1 容器1开始迭代器
        @param end1 容器1结束迭代器
        @param beg2 容器2开始迭代器
        @param end2 容器2结束迭代器
        @param dest  目标容器开始迭代器
        @return 目标容器的最后一个元素的迭代器地址
    */
    vTarget.resize(v1.size() + v2.size());  // 两个容器中取小的。
     itEnd = set_union(v1.begin(), v1.end(), v2.begin(), v2.end(), vTarget.begin());
    copy(vTarget.begin(), itEnd, ostream_iterator<int>(cout, " "));   // 0 1 2 3 4 5 6 7
    cout << endl;
    copy(vTarget.begin(), vTarget.end(), ostream_iterator<int>(cout, " "));   // 0 1 2 3 4 5 6 7 0 0  开辟空间大了
    cout << endl;

    /*
        差集
        set_difference(iterator beg1, iterator end1, iterator beg2, iterator end2, iterator dest);
        set_difference算法 求两个set集合的差集
        注意:两个集合必须是有序序列
        @param beg1 容器1开始迭代器
        @param end1 容器1结束迭代器
        @param beg2 容器2开始迭代器
        @param end2 容器2结束迭代器
        @param dest  目标容器开始迭代器
        @return 目标容器的最后一个元素的迭代器地址
    */
    vTarget.resize(max(v1.size(), v2.size()));  
    // v1 与 v2 的差集
    itEnd = set_difference(v1.begin(), v1.end(), v2.begin(), v2.end(), vTarget.begin());
    copy(vTarget.begin(), itEnd, ostream_iterator<int>(cout, " "));   // 0 1 2
    cout << endl;
}

int main()
{
    test();
    return EXIT_SUCCESS;
}

 

posted on 2022-04-13 18:19  软饭攻城狮  阅读(20)  评论(0编辑  收藏  举报

导航