C++ STL 算法

一雏赦、算法概述

算法主要是由頭文件<algorithm><functional><numeric>組成恰响。

  • <algorithm>是所有STL頭文件中最大的一個,其中常用的功能涉及到比較趣钱,交換,查找,遍歷胚宦,復(fù)制首有,修改燕垃,反轉(zhuǎn),排序井联,合并等...
  • <numeric>體積很小卜壕,只包括在幾個序列容器上進(jìn)行的簡單運(yùn)算的模板函數(shù).
  • <functional> 定義了一些模板類,用以聲明函數(shù)對象。

二烙常、常用遍歷算法

2.1 for_each 算法 遍歷

    遍歷算法 遍歷容器元素
    @param beg 開始迭代器
    @param end 結(jié)束迭代器
    @param _callback  函數(shù)回調(diào)或者函數(shù)對象
    @return 函數(shù)對象
    for_each(iterator beg, iterator end, _callback);
struct myPrint
{
public:
    myPrint()
    {
        a = 0;
    }
    void operator()(const int val)
    {
        cout << val << " ";
        a++;
    }

public:
    int a;
};

void test01()
{
    vector<int> v;
    v.push_back(10);
    v.push_back(20);
    v.push_back(30);
    v.push_back(40);
    v.push_back(50);

   /*
        template <class _InputIterator, class _Function>
        inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
        _Function  for_each(_InputIterator __first, _InputIterator __last, _Function __f)
        {
            for (; __first != __last; ++__first)
                __f(*__first);
            return __f;
        }
   */
    myPrint m = for_each(v.begin(), v.end(), myPrint()); // myPrint() 匿名函數(shù)
    cout << endl; // 10 20 30 40 50 
    cout << m.a << endl; // 5
}

2.2 transform算法

    transform算法 將指定容器區(qū)間元素搬運(yùn)到另一容器中
    注意 : transform 不會給目標(biāo)容器分配內(nèi)存轴捎,所以需要我們提前分配好內(nèi)存
    @param beg1 源容器開始迭代器
    @param end1 源容器結(jié)束迭代器
    @param beg2 目標(biāo)容器開始迭代器
    @param _callback 回調(diào)函數(shù)或者函數(shù)對象
    @return 返回目標(biāo)容器迭代器
    transform(iterator beg1, iterator end1, iterator beg2, _callbakc)
// 將指定容器區(qū)間元素搬運(yùn)到另一容器中
struct MyAdd
{
    int operator()(int v1)
    {
        return v1 + 100;
    }
};

void test02()
{
    vector<int> v;
    v.push_back(10);
    v.push_back(20);
    v.push_back(30);
    v.push_back(40);
    v.push_back(50);

    vector<int> v2;
    v2.resize(v.size()); // 要手動分配空間
    /*
        _OutputIterator transform(_InputIterator __first, _InputIterator __last, _OutputIterator __result, _UnaryOperation __op)
        {
        for (; __first != __last; ++__first, (void) ++__result)
            *__result = __op(*__first);
        return __result;
        }
    */
    transform(v.begin(), v.end(), v2.begin(), MyAdd());
    for_each(v2.begin(), v2.end(), myPrint()); // 110 120 130 140 150
    cout << endl;
}
// 把兩個容器的元素處理后放到第三個容器
struct MyAdd2
{
    int operator()(int v1, int v2)
    {
        return v1 + v2;
    }
};
void test03()
{
    vector<int> v;
    v.push_back(10);
    v.push_back(20);
    v.push_back(30);
    v.push_back(40);
    v.push_back(50);

    vector<int> v2;
    v2.push_back(100);
    v2.push_back(200);
    v2.push_back(300);
    v2.push_back(400);
    v2.push_back(500);
    v2.push_back(600);

    int len = v.size() > v2.size() ? v.size() : v2.size();

    vector<int> v3;
    v3.resize(len);

    /*
        _OutputIterator transform(_InputIterator1 __first1, _InputIterator1 __last1, _InputIterator2 __first2,
                _OutputIterator __result, _BinaryOperation __binary_op)
        {
        for (; __first1 != __last1; ++__first1, (void) ++__first2, ++__result)
            *__result = __binary_op(*__first1, *__first2);
        return __result;
        }
    */
    transform(v.begin(), v.end(), v2.begin(), v3.begin(), MyAdd2());
    for_each(v3.begin(), v3.end(), myPrint()); // 110 220 330 440 550 0 
    cout << endl;
}

三、查找算法

3.1 find算法 查找元素

    find算法 查找元素
    @param beg 容器開始迭代器
    @param end 容器結(jié)束迭代器
    @param value 查找的元素
    @return 返回查找元素的位置
    find(iterator beg, iterator end, value)

3.2 find_if算法 條件查找

    find_if算法 條件查找
    @param beg 容器開始迭代器
    @param end 容器結(jié)束迭代器
    @param  callback 回調(diào)函數(shù)或者謂詞(返回bool類型的函數(shù)對象)
    @return bool 查找返回true 否則false
    find_if(iterator beg, iterator end, _callback);
// 查找基礎(chǔ)類型
struct MyFunc1
{
    bool operator()(int val)
    {
        return val > 30;
    }
};

void test01()
{
    vector<int> v;
    v.push_back(10);
    v.push_back(20);
    v.push_back(30);
    v.push_back(40);
    v.push_back(50);
    /*
        _InputIterator find(_InputIterator __first, _InputIterator __last, const _Tp& __value_)
        {
        for (; __first != __last; ++__first)
        if (*__first == __value_)
            break;
        return __first;
        }
    */
    vector<int>::iterator it = find(v.begin(), v.end(), 20);  // 20
    if (it == v.end())
    {
        cout << "查找失敗" << endl;
    }
    else
    {
        cout << "查找成功"
             << " " << *it << endl;
    }
    /*
        _InputIterator find_if(_InputIterator __first, _InputIterator __last, _Predicate __pred)
        {
        for (; __first != __last; ++__first)
            if (__pred(*__first))
                break;
        return __first;
        }

    */

    vector<int>::iterator it1 = find_if(v.begin(), v.end(), MyFunc1()); // MyFunc1()匿名函數(shù)對象. // 40
    if (it1 == v.end())
    {
        cout << "查找失敗" << endl;
    }
    else
    {
        cout << "查找成功"
             << " " << *it1 << endl;
    }
}

// 查找對象
class Maker
{
public:
    Maker(string name, int age)
    {
        this->name = name;
        this->age = age;
    }
    bool operator==(const Maker &m2) const
    {
        if (this->name == m2.name && this->age == m2.age)
        {
            return true;
        }
        return false;
    }
    bool operator<(const Maker &m2) const
    {
        return this->age < m2.age;
    }

    bool operator>(const Maker &m2) const 
    {
        return this->age > m2.age;
    }

public:
    string name;
    int age;
};

struct MyFindMaker : public binary_function<Maker, Maker, bool>
{
    bool operator()(Maker m, Maker m2) const
    {
        return m.name == m2.name && m.age == m2.age;
    }
};

void test02()
{
    vector<Maker> v;
    v.push_back(Maker("aaa1", 18));
    v.push_back(Maker("aaa2", 19));
    v.push_back(Maker("aaa3", 20));
    v.push_back(Maker("aaa4", 21));
    v.push_back(Maker("aaa5", 22));

    vector<Maker>::iterator it = find(v.begin(), v.end(), Maker("aaa2", 19));

    if (it == v.end())
    {
        cout << "查找失敗" << endl;
    }
    else
    {
        cout << "查找成功"
             << " " << (*it).name << " " << (*it).age << endl;
    }

    cout << "-----------------" << endl;

    Maker m = Maker("aaa2", 19);
    it = find_if(v.begin(), v.end(), bind2nd(MyFindMaker(), m));

    if (it == v.end())
    {
        cout << "查找失敗" << endl;
    }
    else
    {
        cout << "查找成功"
             << " " << (*it).name << " " << (*it).age << endl;
    }
}

3.3 adjacent_find算法

    adjacent_find算法 查找相鄰重復(fù)元素
    @param beg 容器開始迭代器
    @param end 容器結(jié)束迭代器
    @param  _callback 回調(diào)函數(shù)或者謂詞(返回bool類型的函數(shù)對象)
    @return 返回相鄰元素的第一個位置的迭代器
    adjacent_find(iterator beg, iterator end, _callback);
bool MyFunc2(const Maker &m1,const Maker &m2){
    return m1.age == m2.age && m1.name == m2.name;
}

void test03()
{
    vector<int> v;
    v.push_back(10);
    v.push_back(20);
    v.push_back(40);
    v.push_back(40);
    v.push_back(50);

    /*
        _ForwardIterator adjacent_find(_ForwardIterator __first, _ForwardIterator __last)
        {
            typedef typename iterator_traits<_ForwardIterator>::value_type __v;
            return _VSTD::adjacent_find(__first, __last, __equal_to<__v>());
        }

        adjacent_find(_ForwardIterator __first, _ForwardIterator __last, _BinaryPredicate __pred)
        {
            if (__first != __last)
            {
                _ForwardIterator __i = __first;
                while (++__i != __last)
                {
                    if (__pred(*__first, *__i))
                        return __first;
                    __first = __i;
                }
            }
            return __last;
        }

    */

    vector<int>::iterator it = adjacent_find(v.begin(), v.end()); // 成功
    if (it == v.end())
    {
        cout << "查找相鄰重復(fù)元素失敗" << endl;
    }
    else
    {
        cout << "查找相鄰重復(fù)元素成功" << " " << *it << endl;
    }

    vector<Maker> v2;
    v2.push_back(Maker("aaa1", 18));
    v2.push_back(Maker("aaa2", 19));
    v2.push_back(Maker("aaa3", 20));
    v2.push_back(Maker("aaa4", 20));
    v2.push_back(Maker("aaa3", 20));

    // 查找對象 需要提供operater== 或者謂詞
    vector<Maker>::iterator it2 = adjacent_find(v2.begin(), v2.end(),MyFunc2); // 失敗
    if (it2 == v2.end())
    {
        cout << "查找相鄰重復(fù)元素失敗" << endl;
    }
    else
    {
        cout << "查找相鄰重復(fù)元素成功" << " " << it2->name << " " << it2->age << endl;
    }
}

3.4 binary_search算法

    binary_search算法 二分查找法
    注意: 在無序序列中不可用
    @param beg 容器開始迭代器
    @param end 容器結(jié)束迭代器
    @param value 查找的元素
    @return bool 查找返回true 否則false

    bool binary_search(iterator beg, iterator end, value);

void test04() {
    vector<int> v;
    v.push_back(10);
    v.push_back(20);
    v.push_back(30);
    v.push_back(40);
    v.push_back(50);
    v.push_back(60);

    /*
        bool binary_search(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value_)
        {
            return _VSTD::binary_search(__first, __last, __value_,
                                    __less<typename iterator_traits<_ForwardIterator>::value_type, _Tp>());
        }
    */
    // 升序 需要使用less<int>() 做謂詞進(jìn)行二分查找
    bool res1 = binary_search(v.begin(),v.end(),30); // 查找成功
    if(res1){
        cout << "查找成功" << endl;
    }else{
        cout << "查找失敗" << endl;
    }

    vector<int> v2;
    v2.push_back(60);
    v2.push_back(50);
    v2.push_back(40);
    v2.push_back(30);
    v2.push_back(20);
    v2.push_back(10);

    // 降序 需要使用greater<int>()做謂詞進(jìn)行二分查找
    bool res2 = binary_search(v2.begin(),v2.end(),40,greater<int>()); // 查找成功
    if(res2){
        cout << "查找成功" << endl;
    }else{
        cout << "查找失敗" << endl;
    }

}

bool MyFunc3(const Maker &m1,const Maker &m2)
{
    return m1.age < m2.age; 
}

bool MyFunc4(const Maker &m1,const Maker &m2)
{
    return m1.age > m2.age; 
}
// 二分查找對象
void test05() {

    vector<Maker> vs;
    vs.push_back(Maker("aaa1", 18));
    vs.push_back(Maker("aaa2", 19));
    vs.push_back(Maker("aaa3", 20));
    vs.push_back(Maker("aaa4", 21));
    vs.push_back(Maker("aaa5", 22));
    vs.push_back(Maker("aaa6", 23));

    // 升序 需要重載< 或謂詞<
    // bool res1 = binary_search(vs.begin(),vs.end(),Maker("aaa2",19));
    bool res1 = binary_search(vs.begin(),vs.end(),Maker("aaa5",22),MyFunc3);
    if(res1){
        cout << "查找成功" << endl;
    }else{
        cout << "查找失敗" << endl;
    }


    vector<Maker> vs2;
    vs2.push_back(Maker("aaa1", 22));
    vs2.push_back(Maker("aaa2", 21));
    vs2.push_back(Maker("aaa3", 20));
    vs2.push_back(Maker("aaa4", 19));
    vs2.push_back(Maker("aaa5", 18));
    vs2.push_back(Maker("aaa6", 17));

    // 降序 需要重載> 或者 提供謂詞>
    // bool res2 = binary_search(vs2.begin(),vs2.end(),Maker("aaa4",19),greater<Maker>());
    bool res2 = binary_search(vs2.begin(),vs2.end(),Maker("aaa2",21),MyFunc4);
    if(res2){
        cout << "查找成功" << endl;
    }else{
        cout << "查找失敗" << endl;
    }

}

3.5 count算法

    count算法 統(tǒng)計(jì)元素出現(xiàn)次數(shù)
    @param beg 容器開始迭代器
    @param end 容器結(jié)束迭代器
    @param  value 查找的數(shù)據(jù)
    @return int返回元素個數(shù)
    count(iterator beg, iterator end, value);
void test06()
{
    vector<int> v;
    v.push_back(10);
    v.push_back(20);
    v.push_back(20);
    v.push_back(40);
    v.push_back(20);
    v.push_back(60);

    int res = count(v.begin(),v.end(),20); // 3
    cout <<"出現(xiàn)的次數(shù): " << res <<endl;
}

3.6 count_if

    count_if 算法 統(tǒng)計(jì)元素出現(xiàn)次數(shù)
    @param beg 容器開始迭代器
    @param end 容器結(jié)束迭代器
    @param  callback 回調(diào)函數(shù)或者謂詞(返回bool類型的函數(shù)對象)
    @return int返回元素個數(shù)

    count_if(iterator beg, iterator end, _callback);
struct MyFunc5:public binary_function<int, int, bool>
{
    bool operator()(int val1,int val2) const
    {
        return val1 > val2;
    }
};

bool MyFunc6(int val1,int val2){
    return val1 < val2;
}

void test07()
{
    vector<int> v;
    v.push_back(10);
    v.push_back(20);
    v.push_back(20);
    v.push_back(40);
    v.push_back(20);
    v.push_back(60);

    int res1 = count_if(v.begin(),v.end(),bind2nd(MyFunc5(),20)); // > 20
    cout <<"出現(xiàn)的次數(shù): " << res1 <<endl; // 2

    int res2 = count_if(v.begin(),v.end(),bind2nd(ptr_fun(MyFunc6),20));// <20
    cout <<"出現(xiàn)的次數(shù): " << res2 <<endl; // 1

    int res3 = count_if(v.begin(),v.end(),not1(bind2nd(MyFunc5(),20))); // <= 20 
    cout <<"出現(xiàn)的次數(shù): " << res3 <<endl; // 4

}

四蚕脏、排序算法

4.1 merge算法

    merge算法 容器元素合并侦副,并存儲到另一容器中
    @param beg1 容器1開始迭代器
    @param end1 容器1結(jié)束迭代器
    @param beg2 容器2開始迭代器
    @param end2 容器2結(jié)束迭代器
    @param dest  目標(biāo)容器開始迭代器
    merge(iterator beg1, iterator end1, iterator beg2, iterator end2, iterator dest)
void test01()
{

    vector<int> v1;
    vector<int> v2;

    for(int i=0; i<5; i++){
        v1.push_back(i+1);
        v2.push_back(i+2);
    }

    vector<int> v3;
    v3.resize(v1.size() + v2.size());

    /*
        _OutputIterator merge(_InputIterator1 __first1, _InputIterator1 __last1,
        _InputIterator2 __first2, _InputIterator2 __last2, _OutputIterator __result, _Compare __comp)
        {
           typedef typename __comp_ref_type<_Compare>::type _Comp_ref;
           return _VSTD::__merge<_Comp_ref>(__first1, __last1, __first2, __last2, __result, __comp);
        }
    */
    /*

template <class _Compare, class _InputIterator1, class _InputIterator2, class _OutputIterator>
_OutputIterator
__merge(_InputIterator1 __first1, _InputIterator1 __last1,
        _InputIterator2 __first2, _InputIterator2 __last2, _OutputIterator __result, _Compare __comp)
{
    for (; __first1 != __last1; ++__result)
    {
        if (__first2 == __last2)
            return _VSTD::copy(__first1, __last1, __result);
        if (__comp(*__first2, *__first1))
        {
            *__result = *__first2;
            ++__first2;
        }
        else
        {
            *__result = *__first1;
            ++__first1;
        }
    }
    return _VSTD::copy(__first2, __last2, __result);
}

   */
    // 如果數(shù)據(jù)是升序,那么第6個參數(shù)默認(rèn)為less驼鞭,結(jié)果為升序排列
    merge(v1.begin(),v1.end(),v2.begin(),v2.end(),v3.begin()); // 1 2 2 3 3 4 4 5 5 6
    for_each(v3.begin(),v3.end(),MyPrint);
    cout << endl;

    v1.clear();
    v2.clear();

    for(int i=5; i>0; i--){
        v1.push_back(i+4);
        v2.push_back(i+2);
    }
    v3.resize(v1.size() + v2.size());
    // 如果數(shù)據(jù)是降序秦驯,那么第6個參數(shù)就要為greator,結(jié)果為降序序排列
    merge(v1.begin(),v1.end(),v2.begin(),v2.end(),v3.begin(),greater<int>()); // 9 8 7 7 6 6 5 5 4 3
    for_each(v3.begin(),v3.end(),MyPrint);
    cout << endl;
}

4.2 sort算法

    sort算法 容器元素排序
    注意:容器必須是有序的
    @param beg 容器1開始迭代器
    @param end 容器1結(jié)束迭代器
    @param _callback 回調(diào)函數(shù)或者謂詞(返回bool類型的函數(shù)對象)
    sort(iterator beg, iterator end, _callback)

void test02()
{
    vector<int> v;
    v.push_back(80);
    v.push_back(20);
    v.push_back(70);
    v.push_back(40);
    v.push_back(30);

    sort(v.begin(),v.end()); // 20 30 40 70 80
    for_each(v.begin(),v.end(),MyPrint);
    cout << endl;

    sort(v.begin(),v.end(),greater<int>()); // 80 70 40 30 20 
    for_each(v.begin(),v.end(),MyPrint);
    cout << endl;

    // 如果元素是對象终议,需要寫第三個參數(shù)汇竭,謂詞
    // sort(容器開始迭代器,容器結(jié)束迭代器,謂詞);

}

4.3 random_shuffle算法

    random_shuffle算法 對指定范圍內(nèi)的元素隨機(jī)調(diào)整次序
    @param beg 容器開始迭代器
    @param end 容器結(jié)束迭代器
    random_shuffle(iterator beg, iterator end)

void test03()
{
    vector<int> v1;
    for(int i=0; i<10; i++){
        v1.push_back(i+1);
    }
    for_each(v1.begin(),v1.end(),MyPrint);
    cout << endl;

    // 加隨機(jī)種子,使得每次打亂結(jié)果不一樣
    srand((unsigned int)time(NULL));
    random_shuffle(v1.begin(),v1.end());
    for_each(v1.begin(),v1.end(),MyPrint); // 7 1 4 6 8 9 5 2 3 10 
    cout << endl;



}

4.4 reverse算法

    reverse算法 反轉(zhuǎn)指定范圍的元素
    @param beg 容器開始迭代器
    @param end 容器結(jié)束迭代器
    reverse(iterator beg, iterator end)

void test04()
{
    vector<int> v1;
    for(int i=0; i<10; i++){
        v1.push_back(i+1);
    }

    for_each(v1.begin(),v1.end(),MyPrint); // 1 2 3 4 5 6 7 8 9 10
    cout << endl;

    reverse(v1.begin(),v1.end());
    for_each(v1.begin(),v1.end(),MyPrint); // 10 9 8 7 6 5 4 3 2 1
    cout << endl;

}

五穴张、拷貝和替換算法

5.1 copy算法

    copy算法 將容器內(nèi)指定范圍的元素拷貝到另一容器中
    @param beg 容器開始迭代器
    @param end 容器結(jié)束迭代器
    @param dest 目標(biāo)容器開始迭代器
    copy(iterator beg, iterator end, iterator dest)
void test01()
{
    vector<int> v;
    v.push_back(10);
    v.push_back(5);
    v.push_back(7);
    v.push_back(9);
    v.push_back(6);

    vector<int> v2;
    v2.resize(v.size());

    copy(v.begin(),v.end(),v2.begin()); // 10 5 7 9 6
    for_each(v2.begin(),v2.end(),MyPrint);
    cout<<endl;


}

5.2 replace算法

    replace算法 將容器內(nèi)指定范圍的舊元素修改為新元素
    @param beg 容器開始迭代器
    @param end 容器結(jié)束迭代器
    @param oldvalue 舊元素
    @param oldvalue 新元素
    replace(iterator beg, iterator end, oldvalue, newvalue)

void test02()
{
    vector<int> v;
    v.push_back(10);
    v.push_back(5);
    v.push_back(7);
    v.push_back(9);
    v.push_back(6);
    for_each(v.begin(),v.end(),MyPrint);
    cout<<endl;

    replace(v.begin(),v.end(),9,100); // 10 5 7 100 6 
    for_each(v.begin(),v.end(),MyPrint);
    cout<<endl;

}

5.3 replace_if算法

/*
    replace_if算法 將容器內(nèi)指定范圍滿足條件的元素替換為新元素
    @param beg 容器開始迭代器
    @param end 容器結(jié)束迭代器
    @param callback函數(shù)回調(diào)或者謂詞(返回Bool類型的函數(shù)對象)
    @param oldvalue 新元素
    replace_if(iterator beg, iterator end, _callback, newvalue)
*/
struct MyFunc1: public binary_function<int,int,bool>
{
    bool operator()(int v1,int v2) const
    {
        return v1 > v2;
    }
};


void test03()
{
    vector<int> v;
    v.push_back(8);
    v.push_back(5);
    v.push_back(6);
    v.push_back(7);
    v.push_back(9);

    for_each(v.begin(),v.end(),MyPrint);
    cout<<endl;
    /*
        void replace_if(_ForwardIterator __first, _ForwardIterator __last, _Predicate __pred, const _Tp& __new_value)
        {
            for (; __first != __last; ++__first)
                if (__pred(*__first))
                    *__first = __new_value;
        }

    */

    replace_if(v.begin(),v.end(),bind2nd(MyFunc1(),6),100);
    for_each(v.begin(),v.end(),MyPrint);
    cout<<endl;

    replace_if(v.begin(),v.end(),bind1st(MyFunc1(),6),100);
    for_each(v.begin(),v.end(),MyPrint);
    cout<<endl;


}

5.4 swap算法

/*
    swap算法 互換兩個容器的元素
    @param c1容器1
    @param c2容器2
    swap(container c1, container c2)
*/
void test04()
{
    vector<int> v1;
    v1.push_back(8);
    v1.push_back(5);
    v1.push_back(6);
    v1.push_back(7);
    v1.push_back(9);

    vector<int> v2;
    v2.push_back(108);
    v2.push_back(105);
    v2.push_back(106);

    swap(v1,v2);

    for_each(v1.begin(),v1.end(),MyPrint);
    cout<<endl;

    for_each(v2.begin(),v2.end(),MyPrint);
    cout<<endl;

}

六细燎、算術(shù)生成算法

#include <numeric> // 算術(shù)生成算法頭文件

6.1 accumulate算法

/*
    accumulate算法 計(jì)算容器元素累計(jì)總和
    @param beg 容器開始迭代器
    @param end 容器結(jié)束迭代器
    @param value累加值
    accumulate(iterator beg, iterator end, value)
*/
void test01()
{
    vector<int> v1;
    v1.push_back(10);
    v1.push_back(20);
    v1.push_back(30);
    v1.push_back(40);
    /*
        accumulate(_InputIterator __first, _InputIterator __last, _Tp __init)
        {
            for (; __first != __last; ++__first)
                __init = __init + *__first;
            return __init;
        }

    */
    // 默認(rèn) 加法
    int res1 = accumulate(v1.begin(),v1.end(),0);
    cout << res1 << endl;

    // 指定 減法
    int res2 = accumulate(v1.begin(),v1.end(),0,minus<int>());
    cout << res2 << endl;
    
    // 指定 乘法
    int res3 = accumulate(v1.begin(),v1.end(),1,multiplies<int>());
    cout << res3 << endl;
}

class Maker
{
public: 
    Maker(int age)
    {
        this->age = age;
    } 
public:
    int age;
};

struct MyMakerPlus
{
    int operator()(int val,Maker &m){
        return val + m.age;
    }
};


void test02()
{
    vector<Maker> v;
    v.push_back(Maker(10));
    v.push_back(Maker(20));
    v.push_back(Maker(30));

    int ret = accumulate(v.begin(),v.end(),0,MyMakerPlus());
    cout << ret << endl;
}

6.2 fill算法

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

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

void test03()
{
    vector<int> v1;
    v1.push_back(10);
    v1.push_back(20);
    v1.push_back(30);
    v1.push_back(40);

    fill(v1.begin(),v1.end(),50);
    for_each(v1.begin(),v1.end(),MyPrint);
    cout << endl;

    vector<int> v2;
    v2.resize(10); // 要開辟空間
    fill(v2.begin(),v2.end(),50);
    for_each(v2.begin(),v2.end(),MyPrint);
    cout << endl;
}

七、集合算法

7.1 set_intersection算法

/*
    set_intersection算法 求兩個set集合的交集
    注意:兩個集合必須是有序序列
    @param beg1 容器1開始迭代器
    @param end1 容器1結(jié)束迭代器
    @param beg2 容器2開始迭代器
    @param end2 容器2結(jié)束迭代器
    @param dest  目標(biāo)容器開始迭代器
    @return 目標(biāo)容器的最后一個元素的迭代器地址
    set_intersection(iterator beg1, iterator end1, iterator beg2, iterator end2, iterator dest)
*/
void MyPrint(int val) {
    cout << val << " ";
}

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

    vector<int> v2;
    for(int i=5; i<10; i++){
        v2.push_back(i+2);
    }

    vector<int> v3;
    v3.resize(min(v1.size(),v2.size()));

    vector<int>::iterator it =  set_intersection(v1.begin(),v1.end(),v2.begin(),v2.end(),v3.begin());
    for_each(v3.begin(),v3.end(),MyPrint);
    cout<<endl;

    cout <<"---------------"<<endl;
    // 去除因開辟空間多出的默認(rèn)值
    cout << *it << endl;
    v3.erase(it,v3.end());
    for_each(v3.begin(),v3.end(),MyPrint);
    cout<<endl;
}

7.2 set_union算法

/*
    set_union算法 求兩個set集合的并集
    注意:兩個集合必須是有序序列
    @param beg1 容器1開始迭代器
    @param end1 容器1結(jié)束迭代器
    @param beg2 容器2開始迭代器
    @param end2 容器2結(jié)束迭代器
    @param dest  目標(biāo)容器開始迭代器
    @return 目標(biāo)容器的最后一個元素的迭代器地址
    set_union(iterator beg1, iterator end1, iterator beg2, iterator end2, iterator dest)
*/

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

    vector<int> v2;
    for(int i=5; i<10; i++){
        v2.push_back(i);
    }

    vector<int> v3;
    v3.resize(v1.size()+v2.size());
    vector<int>::iterator it = set_union(v1.begin(),v1.end(),v2.begin(),v2.end(),v3.begin());
    for_each(v3.begin(),v3.end(),MyPrint);
    cout<<endl;

    cout <<"---------------"<<endl;
    // 去除因開辟空間多出的默認(rèn)值
    cout << *it << endl;
    v3.erase(it,v3.end());
    for_each(v3.begin(),v3.end(),MyPrint);
    cout<<endl;

}

7.3 set_difference算法

/*
    set_difference算法 求兩個set集合的差集
    注意:兩個集合必須是有序序列
    @param beg1 容器1開始迭代器
    @param end1 容器1結(jié)束迭代器
    @param beg2 容器2開始迭代器
    @param end2 容器2結(jié)束迭代器
    @param dest  目標(biāo)容器開始迭代器
    @return 目標(biāo)容器的最后一個元素的迭代器地址
    set_difference(iterator beg1, iterator end1, iterator beg2, iterator end2, iterator dest)
*/
// 假如 A集合 1皂甘,2玻驻,3,4偿枕,5 B集合 2璧瞬,3,4渐夸,5嗤锉,6,A-B 為1,B-A為6
void test03()
{
    vector<int> v1;
    for(int i=0; i<5; i++){
        v1.push_back(i+1);
    }

    vector<int> v2;
    for(int i=0; i<5; i++){
        v2.push_back(i+2);
    }

    vector<int> v3;
    v3.resize(min(v1.size(),v2.size()));

    vector<int>::iterator it = set_difference(v1.begin(),v1.end(),v2.begin(),v2.end(),v3.begin());
    for_each(v3.begin(),v3.end(),MyPrint);
    cout<<endl;

    set_difference(v2.begin(),v2.end(),v1.begin(),v1.end(),v3.begin());
    for_each(v3.begin(),v3.end(),MyPrint);
    cout<<endl;
}

八墓塌、綜合案例

學(xué)校演講比賽介紹
1)某市舉行一場演講比賽( speech_contest )瘟忱,共有24個人參加。比賽共三輪苫幢,前兩輪為淘汰賽访诱,第三輪為決賽。
2)比賽方式:分組比賽韩肝,每組6個人触菜;選手每次要隨機(jī)分組,進(jìn)行比賽哀峻;
第一輪分為4個小組涡相,每組6個人哲泊。比如100-105為一組,106-111為第二組漾峡,依次類推攻旦,
每人分別按照抽簽(draw)順序演講喻旷。當(dāng)小組演講完后生逸,淘汰組內(nèi)排名最后的三個選手,然后繼續(xù)下一個小組的比賽且预。
第二輪分為2個小組槽袄,每組6人。比賽完畢锋谐,淘汰組內(nèi)排名最后的三個選手遍尺,然后繼續(xù)下一個小組的比賽。
第三輪只剩下6個人涮拗,本輪為決賽乾戏,選出前三名。
4)比賽評分:10個評委打分三热,去除最低鼓择、最高分,求平均分
每個選手演講完由10個評委分別打分就漾。該選手的最終得分是去掉一個最高分和一個最低分呐能,求得剩下的8個成績的平均分。
選手的名次按得分降序排列抑堡,若得分一樣摆出,按參賽號升序排名。

用STL編程首妖,求解這個問題
1)請打印出所有選手的名字與參賽號偎漫,并以參賽號的升序排列。
2)打印每一輪比賽后有缆,小組比賽成績和小組晉級名單
3)打印決賽前三名象踊,選手名稱、成績妒貌。


#include <iostream>
#include <algorithm>
#include <numeric>
#include <functional>
#include <vector>
#include <map>
#include <deque>
#include <ctime>

using namespace std;

class Player
{
public:
    string mName;
    int mAge;
    int mScore[3]; // 選手最多有3輪比賽成績
};

// 創(chuàng)建選手
void CreatePlayers(vector<int> &v1, map<int, Player> &mlist)
{
    string tempstring = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    for (int i = 0; i < 24; i++)
    {
        Player p;
        p.mName = "選手";
        p.mName += tempstring[i];
        p.mAge = rand() % 5 + 15;

        for (int j = 0; j < 3; j++)
        {
            p.mScore[j] = 0;
        }

        // 生成選手編號
        int ID = 100 + i;
        // 保存選手編號
        v1.push_back(ID);
        // 保存選手信息
        mlist.insert(make_pair(ID, p));
    }
}

// 抽簽
void PlayerByRandom(vector<int> &v)
{
    return random_shuffle(v.begin(), v.end());
}
// 比賽
void StartMatch(int index, vector<int> &v1, map<int, Player> &mlist, vector<int> &v2)
{
    // 定義multimap容器,鍵值是分?jǐn)?shù)通危,實(shí)值是選手編號
    // 降序排列
    multimap<int, int, greater<int> > mGroups;

    for (vector<int>::iterator sit = v1.begin(); sit != v1.end(); ++sit)
    {
        // 評委評分
        deque<int> dScore;
        for (int i = 0; i < 10; i++)
        {
            int score = rand() % 30 + 70;
            dScore.push_back(score);
        }

        // 排序
        sort(dScore.begin(), dScore.end());
        // 去除最高分和最低分
        dScore.pop_front();
        dScore.pop_back();

        // 總分
        int total_score = accumulate(dScore.begin(), dScore.end(), 0);

        // 平均分
        int average_score = total_score / dScore.size();

        // 保存選手分?jǐn)?shù)
        mlist[*sit].mScore[index - 1] = average_score;

        // 把選手放到multimap容器中
        mGroups.insert(make_pair(average_score, *sit));

        // 評比
        if (mGroups.size() == 6)
        {
            // 容器中一共6人 選取前面3位
            int tempIndex = 0;
            for (multimap<int, int>::iterator mit = mGroups.begin(); mit != mGroups.end() && tempIndex < 3; ++mit, ++tempIndex)
            {
                v2.push_back((*mit).second);
            }
            // 清空容器
            mGroups.clear();
        }
    }
}

// 打印本輪晉級選手
void ShowPlayerScore(int index, vector<int> &v, map<int, Player> &mlist)
{
    cout << "第" << index << "輪 晉級名單:" << endl;
    for (vector<int>::iterator it = v.begin(); it != v.end(); ++it)
    {
        cout << "Name: " << mlist[*it].mName << " Age: " << mlist[*it].mAge << " Score: " << mlist[*it].mScore[index - 1] << endl;
    }
}

void test()
{
    vector<int> v1;         // 保存選手編號
    map<int, Player> mlist; // 保存選手信息
    vector<int> v2;         // 保存第一輪晉級選手編號
    vector<int> v3;         // 保存第二輪晉級選手編號
    vector<int> v4;         // 保存第三輪晉級選手編號

    // 創(chuàng)建選手
    CreatePlayers(v1, mlist);

    // 第一輪比賽
    // 抽簽
    PlayerByRandom(v1);
    // 比賽
    StartMatch(1, v1, mlist, v2);
    // 打印本輪晉級選手
    ShowPlayerScore(1, v2, mlist);

    // 第二輪比賽:抽簽 比賽 打印本輪晉級選手
    // 抽簽
    PlayerByRandom(v2);
    // 比賽
    StartMatch(2, v2, mlist, v3);
    // 打印本輪晉級選手
    ShowPlayerScore(2, v3, mlist);

    // 第三輪比賽
    // 抽簽
    PlayerByRandom(v3);
    // 比賽
    StartMatch(3, v3, mlist, v4);
    // 打印本輪晉級選手
    ShowPlayerScore(3, v4, mlist);
}

int main()
{
    srand((unsigned int)time(NULL));
    test();
    return EXIT_SUCCESS;
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市灌曙,隨后出現(xiàn)的幾起案子菊碟,更是在濱河造成了極大的恐慌,老刑警劉巖在刺,帶你破解...
    沈念sama閱讀 206,968評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件逆害,死亡現(xiàn)場離奇詭異头镊,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)魄幕,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,601評論 2 382
  • 文/潘曉璐 我一進(jìn)店門相艇,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人纯陨,你說我怎么就攤上這事坛芽。” “怎么了翼抠?”我有些...
    開封第一講書人閱讀 153,220評論 0 344
  • 文/不壞的土叔 我叫張陵咙轩,是天一觀的道長。 經(jīng)常有香客問我阴颖,道長活喊,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,416評論 1 279
  • 正文 為了忘掉前任量愧,我火速辦了婚禮钾菊,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘偎肃。我一直安慰自己煞烫,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,425評論 5 374
  • 文/花漫 我一把揭開白布软棺。 她就那樣靜靜地躺著红竭,像睡著了一般。 火紅的嫁衣襯著肌膚如雪喘落。 梳的紋絲不亂的頭發(fā)上茵宪,一...
    開封第一講書人閱讀 49,144評論 1 285
  • 那天,我揣著相機(jī)與錄音瘦棋,去河邊找鬼稀火。 笑死,一個胖子當(dāng)著我的面吹牛赌朋,可吹牛的內(nèi)容都是我干的凰狞。 我是一名探鬼主播,決...
    沈念sama閱讀 38,432評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼沛慢,長吁一口氣:“原來是場噩夢啊……” “哼赡若!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起团甲,我...
    開封第一講書人閱讀 37,088評論 0 261
  • 序言:老撾萬榮一對情侶失蹤逾冬,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體身腻,經(jīng)...
    沈念sama閱讀 43,586評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡产还,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,028評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了嘀趟。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片脐区。...
    茶點(diǎn)故事閱讀 38,137評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖她按,靈堂內(nèi)的尸體忽然破棺而出牛隅,到底是詐尸還是另有隱情,我是刑警寧澤尤溜,帶...
    沈念sama閱讀 33,783評論 4 324
  • 正文 年R本政府宣布倔叼,位于F島的核電站汗唱,受9級特大地震影響宫莱,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜哩罪,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,343評論 3 307
  • 文/蒙蒙 一授霸、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧际插,春花似錦碘耳、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,333評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至瑟枫,卻和暖如春斗搞,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背慷妙。 一陣腳步聲響...
    開封第一講書人閱讀 31,559評論 1 262
  • 我被黑心中介騙來泰國打工僻焚, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人膝擂。 一個月前我還...
    沈念sama閱讀 45,595評論 2 355
  • 正文 我出身青樓虑啤,卻偏偏與公主長得像,于是被迫代替她去往敵國和親架馋。 傳聞我的和親對象是個殘疾皇子狞山,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,901評論 2 345

推薦閱讀更多精彩內(nèi)容