Bootstrap

C++ - 泛型算法(algorithm)

一、基础泛型算法

#include <algorithm>

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

1.1 find():

用于搜索无序集合中是否存在某值。搜索范围由iterator[first, last)标出。如果找到目标,find()会返回一个iterator指向该值,否则返回一个iterator指向last。

vector<int>::iterator iter = find(vec.begin(), vec.end(), 3);

1.2 binary_search():

用于有序集合的搜索。如果搜索到目标,就返回true;否则返回false。

bool fjud = binary_search(vec.begin(), vec.end(), 3);

1.3 count():

返回数值相符的元素数目。

int cnt = count(vec.begin(), vec.end(), 4);

1.4 search():

比对某个容器内是否存在某个子序列。若子序列存在则返回一个iterator指向子序列起始处;否则返回一个iterator指向容器末尾。

int arr[3] = {2, 3, 4};
vector<int>::iterator it = search(vec.begin(), vec.end(), arr, arr+3);

1.5 max_element():

vector<int>::iterator elem = max_element(vec.begin(), vec.end());

1.6 copy():

需要确保”目标容器“拥有足够空间放置每个即将到来的元素。

vector<int> temp(vec.size());
copy(vec.begin(), vec.end(), temp.begin());

二、如何设计一个泛型算法 - 编程实例

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

bool less_than(int v1, int v2)
{
    return v1 < v2 ? true : false;
}

vector<int> filter_InitVersion01(const vector<int> &vec, int filter_value, bool (*pred)(int, int))
{
    vector<int> res;
    for (int i = 0; i < vec.size(); ++i)
    {
        if (pred(vec[i], filter_value))
        {
            res.push_back(vec[i]);
        }
    }
    return res;
}

// 使用该函数替换filter函数中的for(){}查找方法。
int count_occurs(const vector<int> &vec, int val)
{
    // const_iterator该类型只能用于读取容器内的元素,但不能改变对象的值。
    vector<int>::const_iterator iter = vec.begin();
    int occurs_count = 0;
    while ((iter = find(iter, vec.end(), val)) != vec.end())
    {
        ++occurs_count;
        ++iter; // 指向下一个元素。
    }
    return occurs_count;
}

// function object:是某种class的实例对象,这类class对function call运算符做了重载操作,如此一来可使function object被当成一般函数来使用。
// #include <functional>
// sort(vec.begin(), vec.end(), greater<int>());
// function object,是我们得以将某组行为传给函数,此法比函数指针的做法效率更高。
vector<int> filter_InitVersion02(const vector<int> &vec, int val, less<int> &lt)
{
    vector<int> res;
    vector<int>::const_iterator iter = vec.begin();

    // bind2nd(lless<int>, val);
    // 会把val绑定于less<int>的第二个参数身上
    // 于是,less<int>会将每个元素拿来和val比较

    // find_if(): 可以使用输入的函数替代等于操作符执行查找功能
    while ((iter = find_if(iter, vec.end(), bind2nd(lt, val))) != vec.end())
    {
        res.push_back(*iter);
        ++iter; // 指向下一个元素。
    }
    return res;
}

// 为了支持多种容器,我们将元素类型参数化,也将应用于元素上的“比较操作”参数化,以便得以同时支持函数指针和fuction object两种方式。
template <typename InputIterator, typename OutputIterator, typename ElemType, typename Comp>
OutputIterator filter(InputIterator first, InputIterator last, OutputIterator at, const ElemType &val, Comp pred)
{
    while ((first = find_if(first, last, bind2nd(pred, val))) != last)
    {
        cout << "found value: " << *first << endl;
        *at++ = *first++;
    }
    return at;
}

int main()
{
    const int elem_size = 8;
    int arr[elem_size] = {1, 5, 10, 15, 20, 25, 10, 15};
    vector<int> vec(arr, arr+elem_size);

    cout << "#filter_InitVersion01: \n";
    vector<int> res = filter_InitVersion01(vec, 8, less_than);
    for (int i = 0; i < res.size(); ++i)
    {
        cout << res[i] << " ";
    }
    cout << endl;

    int arr2[elem_size];
    vector<int> vec2(elem_size);

    cout << "filtering integer array for values less than 8\n";
    filter(arr, arr+elem_size, arr2, 8, less<int>());

    cout << "filtering integer vector for values less than 8\n";
    filter(vec.begin(), vec.end(), vec2.begin(), 8, greater<int>());

    return 0;
}
;