STL中的算法

Posted walkinginthesun

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了STL中的算法相关的知识,希望对你有一定的参考价值。

参考:《STL源码剖析》第6章 算法

#include <iostream>
#include <vector>
#include <functional>


/*********************************************************************/
template<class InputIterator, class T>
T accumulate(InputIterator first, InputIterator last, T init)
{
    for (; first != last; ++first){
        init = init + *first;
    }
    return init;
}

template<class InputIterator, class T, class BinaryOp>
T accumulate(InputIterator first, InputIterator last, T init, BinaryOp f)
{
    for (; first != last; ++first){
        init = f(init, *first);
    }
    return init;
}


int multi(int a, int b)
{
    return a*b;
}
/*********************************************************************/
template<class InputIterator, class OutputIterator>
OutputIterator adjacent_difference(InputIterator first, InputIterator last, OutputIterator result)
{
    *result = *first;
    auto value = *first;
    while (++first != last){
        auto tmp = *first;    // 这一步很重要,避免result与first相同产生错误
        *++result = tmp - value;
        value = tmp;
    }
    return ++result;
}
/*********************************************************************/
template<class T>
T power(T x, int n)
{
    static int cnt = 0;
    cnt++;

    if (n == 0){
        std::cout << "cnt is "<<cnt << std::endl;
        return 1;
    }
    return x*power(x, n - 1);
}


template<class T>
T power_2(T x, int n)
{
    static int cnt = 0;
    cnt++;

    if (n == 0){
        std::cout << "cnt is " << cnt << std::endl;
        return 1;
    }
    if (n & 0x1){
        // n 为奇数
        int result = power_2(x, n >> 1);
        return x*result*result;
    }
    else{
        // n 为偶数
        int result = power_2(x, n >> 1);
        return result*result;
    }
}
/*********************************************************************/
template<class InputIterator>
void for_each(InputIterator first, InputIterator last)
{
    for (; first != last; ++first){
        std::cout << *first << std::endl;
    }
}

template<class InputIterator, class UnaryOp>
void for_each(InputIterator first, InputIterator last, UnaryOp op)
{
    for (; first != last; ++first){
        op(*first);
    }
}

template<class T>
void display(T t)
{
    std::cout << t << std::endl;
}

template<class T>
class Display
{
public:
    void operator()(const T &t){
        std::cout << t << std::endl;
    }
};

/*********************************************************************/
template<class T>
T max(const T &a, const T &b)
{
    return a > b ? a : b;
}

template<class T, class BinaryOp>
T max(const T &a, const T &b, BinaryOp cmp)
{
    return cmp(a,b)? a : b;
}

template<class T>
bool cmp(const T &a, const T &b)
{
    return a < b;
}
/*********************************************************************/
template<class InputIterator1, class InputIterator2, class BinaryOp>
std::pair<InputIterator1, InputIterator2>
mismatch(InputIterator1 first1,
         InputIterator1 last1,
         InputIterator2 first2,
         BinaryOp op)
{
    for (; first1 != last1; ++first1, ++first2){
        if (!op(*first1, *first2)){
            break;
        }
    }
    return std::make_pair(first1, first2);
}

struct int2
{
    int value;
};

bool cmp_int_int2(int a, const int2 &b)
{
    return a == b.value;
}

/*********************************************************************/
template<class ForwardIterator/*, class BinaryOp*/>
ForwardIterator adjacent_find(ForwardIterator first, ForwardIterator last/*, BinaryOp op*/)
{
    for (; first+1 != last;++first){
        if (*first == *(first + 1)){
            return first;
        }
    }
    return last;
}
/*********************************************************************/
// sorted 为前提
template<class InputIterator, class OutputIterator>
OutputIterator merge(InputIterator first1, InputIterator last1,
    InputIterator first2, InputIterator last2,
    OutputIterator result)
{
    while (first1 != last1 && first2 != last2){
        if (*first1 < *first2){
            *result = *first1;
            ++first1;
        }
        else{
            *result = *first2;
            ++first2;
        }
        ++result;
    }
    while (first1 != last1){
        *result++ = *first1++;
    }
    while (first2 != last2){
        *result++ = *first2++;
    }
    return result;
}
/*********************************************************************/
template<class InputIterator>
void iterator_swap(InputIterator first, InputIterator second)
{
    auto tmp = *first;
    *first = *second;
    *second = tmp;
}

template<class BidirectionalIterator, class Predicate>
BidirectionalIterator partition(BidirectionalIterator first, BidirectionalIterator last, Predicate unaryop)
{
    while (true){
        // left
        while (true){
            if (first == last){
                return first;
            }
            if (unaryop(*first)){
                ++first;
            }
            else{
                break;
            }
        }

        // right
        --last;
        while (true){
            if (first == last){
                return first;
            }
            if (!unaryop(*last)){
                --last;
            }
            else{
                break;
            }
        }

        // swap
        iterator_swap(first, last);

        // next
        ++first;
    }
}

bool parity(int n)
{
    return n & 0x1;
}
/*********************************************************************/
// greateast common divisor  ==> gcd
// 辗转相除法 求 最大公约数
// int big = a > b ? a : b;
// int little = a < b ? a : b;
int gcd(int big, int little)
{
    if (big % little == 0){
        return little;
    }
    return gcd(little, big%little);
}
/*********************************************************************/
template<class ForwardIterator>
int my_distance(ForwardIterator first, ForwardIterator last)
{
    int len = 0;
    while (first != last){
        len++;
        first++;
    }
    return len;
}

template<class ForwardIterator>
ForwardIterator my_advance(ForwardIterator first, int steps)
{
    while (steps--){
        first++;
    }
    return first;
}

template<class ForwardIterator, class T>
ForwardIterator lower_bound(ForwardIterator first, ForwardIterator last, const T &value)
{
    int len = my_distance(first, last);
    std::cout << len << std::endl;

    int half = 0;
    ForwardIterator middle;
    while (len > 0){
        half = len >> 1;
        middle = my_advance(first, half);
        std::cout << *middle << std::endl;

        if (*middle < value){
            first = middle;
            ++first;
            len = len - half -1;
        }
        else{
            len = half;
        }
    }
    return first;
}

void test_lower_bound()
{
    std::vector<int> v = {12,17,20,21,22,23,30,33,40};
    std::vector<int>::iterator iter = lower_bound(v.begin(), v.end(), 21);
    std::cout << *iter << std::endl;
}

template<class ForwardIterator, class T>
bool my_binary_search(ForwardIterator first, ForwardIterator last, const T &value)
{
    ForwardIterator iter = lower_bound(first, last, value);
    return iter != last && !(value<*iter);
}

void test_binary_search()
{
    std::vector<int> v = { 12, 17, 20, 21, 22, 23, 30, 33, 40 };
    std::cout << my_binary_search(v.begin(), v.end(), 27) << std::endl;
}


/*********************************************************************/
int main()
{
    std::vector<int> v = { 1, 2, 3, 4, 5 };
    int result = accumulate(v.begin(), v.end(), 0);
    //std::cout << result << std::endl;
    for_each(v.begin(), v.end());

    result = accumulate(v.begin(), v.end(), 1, multi);
    std::cout << result << std::endl;

    result = accumulate(v.begin(), v.end(), 0, std::plus<int>());
    std::cout << result << std::endl;

    result = accumulate(v.begin(), v.end(), 1, std::multiplies<int>());
    std::cout << result << std::endl;

    adjacent_difference(v.begin(), v.end(), v.begin());
    //for (auto e : v){
    //    std::cout << e << std::endl;
    //}
    for_each(v.begin(), v.end(), Display<int>());

    std::cout << power(2, 25) << std::endl;
    std::cout << power_2(2, 25) << std::endl;

    std::cout << max(4, 7) << std::endl;
    std::cout << max(4, 7, cmp<int>) << std::endl;

    std::vector<int> v1 = { 1, 2, 3, 4, 5 };
    std::vector<int2> v2 = { { 1 }, { 2 }, { 5 }, { 4 }, { 5 } };
    std::pair<std::vector<int>::iterator, std::vector<int2>::iterator> result_pair = mismatch(v1.begin(), v1.end(), v2.begin(), cmp_int_int2);
    std::cout << *result_pair.first << " " << result_pair.second->value << std::endl;

    std::vector<int> v3 = { 1, 2, 3, 3, 5 };
    std::vector<int>::iterator iter = adjacent_find<std::vector<int>::iterator>(v3.begin(), v3.end());
    std::cout << "adjacent find " << *iter << " " << *(iter + 1) << std::endl;

    std::vector<int> v4;
    v4.resize(v1.size() + v3.size());
    merge(v1.begin(), v1.end(), v3.begin(), v3.end(), v4.begin());
    for_each(v4.begin(), v4.end());

    std::cout << std::endl;
    partition(v4.begin(), v4.end(), parity);
    for_each(v4.begin(), v4.end());

    std::cout << "gcd(4,10)= " << gcd(4, 10) << std::endl;
    std::cout << "gcd(123456, 7890)= " << gcd(123456, 7890) << std::endl;

    test_lower_bound();
    test_binary_search();

    return 0;
}

以上是关于STL中的算法的主要内容,如果未能解决你的问题,请参考以下文章

C++中STL学习笔记——常见算法操作演示

疯子的算法总结(二) STL Ⅰ 算法 ( algorithm )

STL中的查找算法

图解|从武侠角度探究STL排序算法的奥秘

STL_算法_06_遍历算法

STL中的算法