(四)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;
}

原文地址:https://www.cnblogs.com/walkinginthesun/p/9762138.html

时间: 2024-11-13 10:41:33

(四)STL中的算法的相关文章

STL中排序算法的选择

 当大多数程序员需要对一组对象进行排序的时候,首先想到的一个算法是sort.sort是一个非常不错的算法,但它也并非在任何场合下都是完美无缺的.有时候我们并不需要一个完全的排序操作.比如说,如果我们有一个存放Widget的矢量,而我们希望将质量最好的20个Widget送给最重要的顾客,按照顾客的重要程度送上不同质量的Widget,那么只需要排序出前20个最好的Widget,其他的Widget可以不用排序.在这种情况下,需要的是一种部分排序的功能,而有一个名为partial_sort的算法正好

STL中的算法小结

(1)要运用STL的算法,首先必须包含头文件<algorithm>,某些STL算法用于数值处理,因此被定义于头文件<numeric> (2)所有STL算法都被设计用来处理一个或多个迭代器区间,第一个区间通常以起点和终点表示,至于其他区间,多数情况下你只需提供起点便足以,其终点可以自动以第一个区间的元素数量推断出来,调用者必须保证这些区间的有效性. STL算法采用覆盖模式而非安插模式,所以调用者必须保证目标区间拥有足够的元素空间,当然你也可以运用特殊的安插型迭代器将覆盖模式改变为安插

STL中heap算法(堆算法)

 ①push_heap算法 以下是push_heap算法的实现细节.该函数接收两个迭代器,用来表现一个heap底部容器(vector)的头尾,而且新元素已经插入究竟部的最尾端. template <class RandomAccessIterator> inline void push_heap(RandomAccessIterator first,RandomAccessIterator last) { //注意,此函数被调用时,新元素应已置于底部容器的最尾端 _push_heap_au

STL中排序算法

[1]    push_heap:默认为大根堆,主要是上滤操作. [2]    make_heap:创建堆,默认构建大根堆.他的实现基于这样一个简单的想法:将二叉树中的每个仅二层的子树都构成堆,那么整个数据集的布局几乎即可以满足堆的定义. [3]    pop_heap:将已构成堆的迭代器区间中最大值元素移到区间的最后元素位置.原来的最后元素调整为根结点元素后,再对除最后一个元素之外的区间调整. [4]    sort_heap:堆排序,时间复杂度O(nlog2n).内部通过一个while循环调

STL中简单算法实例sort()、next_permutation()

#include<iostream> #include<string> #include<algorithm> using namespace std; int main() {     string letters;     cout<<"Enter the letters grouping (quit to quit): ";     while(cin>>letters && letters != &qu

STL中的所有算法(70个)

 STL中的所有算法(70个) STL算法部分主要由头文件<algorithm>,<numeric>,<functional>组成.要使用 STL中的算法函数必须包含头文件<algorithm>,对于数值算法须包含<numeric>,<functional>中则定义了一些模板类,用来声明函数对象. STL中算法大致分为四类: 1.非可变序列算法:指不直接修改其所操作的容器内容的算法. 2.可变序列算法:指可以修改它们所操作的容器内

STL中的仿函数

仿函数(functors)在C++标准中采用的名称是函数对象(function objects).仿函数主要用于STL中的算法中,虽然函数指针虽然也可以作为算法的参数,但是函数指针不能满足STL对抽象性的要求,也不能满足软件积木的要求--函数指针无法和STL其他组件搭配,产生更灵活变化. 仿函数本质就是类重载了一个operator(),创建一个行为类似函数的对象.例如下面就是一个仿函数的例 struct plus{ int operator()(const int& x, const int&am

C++11新特性应用--介绍几个新增的便利算法(stl中的heap使用,最大堆)

有的时候为了维护数据,我们使用stl的堆去维护一序列. 首先您要弄清楚堆和栈的区别,即heap和stack stl中的堆默认是最大堆. 先介绍 push_heap,pop_heap,make_heap,sort_heap这四个算法,这四个不是C++11新增加的内容. 首先是如何产生一个最大推: make_heap 原型: template <class RandomAccessIterator> void make_heap (RandomAccessIterator first, Rando

STL中基本的算法(一)

一.replace() 替换算法将指定元素值替换为新值,使用原型如下,将迭代器[first,last)中值为old_value的元素全部替换为new_value值. 函数原型: template < class ForwardIterator, class T > void replace ( ForwardIterator first, ForwardIterator last, const T& old_value, const T& new_value );   参数说明