C++ STL 算法

一、算法概述

算法主要是由头文件<algorithm><functional><numeric>组成。

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

二、常用遍历算法

2.1 for_each 算法 遍历

    遍历算法 遍历容器元素
    @param beg 开始迭代器
    @param end 结束迭代器
    @param _callback  函数回调或者函数对象
    @return 函数对象
    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() 匿名函数
    cout << endl; // 10 20 30 40 50 
    cout << m.a << endl; // 5
}

2.2 transform算法

    transform算法 将指定容器区间元素搬运到另一容器中
    注意 : transform 不会给目标容器分配内存,所以需要我们提前分配好内存
    @param beg1 源容器开始迭代器
    @param end1 源容器结束迭代器
    @param beg2 目标容器开始迭代器
    @param _callback 回调函数或者函数对象
    @return 返回目标容器迭代器
    transform(iterator beg1, iterator end1, iterator beg2, _callbakc)
// 将指定容器区间元素搬运到另一容器中
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 容器结束迭代器
    @param value 查找的元素
    @return 返回查找元素的位置
    find(iterator beg, iterator end, value)

3.2 find_if算法 条件查找

    find_if算法 条件查找
    @param beg 容器开始迭代器
    @param end 容器结束迭代器
    @param  callback 回调函数或者谓词(返回bool类型的函数对象)
    @return bool 查找返回true 否则false
    find_if(iterator beg, iterator end, _callback);
// 查找基础类型
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()匿名函数对象. // 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算法 查找相邻重复元素
    @param beg 容器开始迭代器
    @param end 容器结束迭代器
    @param  _callback 回调函数或者谓词(返回bool类型的函数对象)
    @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 << "查找相邻重复元素失败" << endl;
    }
    else
    {
        cout << "查找相邻重复元素成功" << " " << *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 << "查找相邻重复元素失败" << endl;
    }
    else
    {
        cout << "查找相邻重复元素成功" << " " << it2->name << " " << it2->age << endl;
    }
}

3.4 binary_search算法

    binary_search算法 二分查找法
    注意: 在无序序列中不可用
    @param beg 容器开始迭代器
    @param end 容器结束迭代器
    @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>() 做谓词进行二分查找
    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>()做谓词进行二分查找
    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算法 统计元素出现次数
    @param beg 容器开始迭代器
    @param end 容器结束迭代器
    @param  value 查找的数据
    @return int返回元素个数
    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 <<"出现的次数: " << res <<endl;
}

3.6 count_if

    count_if 算法 统计元素出现次数
    @param beg 容器开始迭代器
    @param end 容器结束迭代器
    @param  callback 回调函数或者谓词(返回bool类型的函数对象)
    @return int返回元素个数

    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 <<"出现的次数: " << res1 <<endl; // 2

    int res2 = count_if(v.begin(),v.end(),bind2nd(ptr_fun(MyFunc6),20));// <20
    cout <<"出现的次数: " << res2 <<endl; // 1

    int res3 = count_if(v.begin(),v.end(),not1(bind2nd(MyFunc5(),20))); // <= 20 
    cout <<"出现的次数: " << res3 <<endl; // 4

}

四、排序算法

4.1 merge算法

    merge算法 容器元素合并,并存储到另一容器中
    @param beg1 容器1开始迭代器
    @param end1 容器1结束迭代器
    @param beg2 容器2开始迭代器
    @param end2 容器2结束迭代器
    @param dest  目标容器开始迭代器
    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);
}

   */
    // 如果数据是升序,那么第6个参数默认为less,结果为升序排列
    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());
    // 如果数据是降序,那么第6个参数就要为greator,结果为降序序排列
    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结束迭代器
    @param _callback 回调函数或者谓词(返回bool类型的函数对象)
    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;

    // 如果元素是对象,需要写第三个参数,谓词
    // sort(容器开始迭代器,容器结束迭代器,谓词);

}

4.3 random_shuffle算法

    random_shuffle算法 对指定范围内的元素随机调整次序
    @param beg 容器开始迭代器
    @param end 容器结束迭代器
    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;

    // 加随机种子,使得每次打乱结果不一样
    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算法 反转指定范围的元素
    @param beg 容器开始迭代器
    @param end 容器结束迭代器
    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算法 将容器内指定范围的元素拷贝到另一容器中
    @param beg 容器开始迭代器
    @param end 容器结束迭代器
    @param dest 目标容器开始迭代器
    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算法 将容器内指定范围的旧元素修改为新元素
    @param beg 容器开始迭代器
    @param end 容器结束迭代器
    @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算法 将容器内指定范围满足条件的元素替换为新元素
    @param beg 容器开始迭代器
    @param end 容器结束迭代器
    @param callback函数回调或者谓词(返回Bool类型的函数对象)
    @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;

}

六、算术生成算法

#include <numeric> // 算术生成算法头文件

6.1 accumulate算法

/*
    accumulate算法 计算容器元素累计总和
    @param beg 容器开始迭代器
    @param end 容器结束迭代器
    @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;
        }

    */
    // 默认 加法
    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 容器结束迭代器
    @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结束迭代器
    @param beg2 容器2开始迭代器
    @param end2 容器2结束迭代器
    @param dest  目标容器开始迭代器
    @return 目标容器的最后一个元素的迭代器地址
    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;
    // 去除因开辟空间多出的默认值
    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结束迭代器
    @param beg2 容器2开始迭代器
    @param end2 容器2结束迭代器
    @param dest  目标容器开始迭代器
    @return 目标容器的最后一个元素的迭代器地址
    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;
    // 去除因开辟空间多出的默认值
    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结束迭代器
    @param beg2 容器2开始迭代器
    @param end2 容器2结束迭代器
    @param dest  目标容器开始迭代器
    @return 目标容器的最后一个元素的迭代器地址
    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;
}

八、综合案例

学校演讲比赛介绍
1)某市举行一场演讲比赛( speech_contest ),共有24个人参加。比赛共三轮,前两轮为淘汰赛,第三轮为决赛。
2)比赛方式:分组比赛,每组6个人;选手每次要随机分组,进行比赛;
第一轮分为4个小组,每组6个人。比如100-105为一组,106-111为第二组,依次类推,
每人分别按照抽签(draw)顺序演讲。当小组演讲完后,淘汰组内排名最后的三个选手,然后继续下一个小组的比赛。
第二轮分为2个小组,每组6人。比赛完毕,淘汰组内排名最后的三个选手,然后继续下一个小组的比赛。
第三轮只剩下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轮比赛成绩
};

// 创建选手
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容器,键值是分数,实值是选手编号
    // 降序排列
    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();

        // 保存选手分数
        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;         // 保存第三轮晋级选手编号

    // 创建选手
    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;
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,839评论 6 482
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,543评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 153,116评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,371评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,384评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,111评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,416评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,053评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,558评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,007评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,117评论 1 334
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,756评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,324评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,315评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,539评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,578评论 2 355
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,877评论 2 345

推荐阅读更多精彩内容