• 大话STL第十期终章——算法


    这一期就是我们STL基本学习的最后一期了~~完结撒花~

    前期系列内容回顾:

    关注主页不迷路:Oorik的博客_CSDN博客-C,C++领域博主 

     文章篇幅较长,我会根据功能分类进行演示和总结,可以跳转自己需要的地方

    文章目录

    STL常用算法概述:

    常用遍历算法:

    for_each:遍历容器元素

    transform:搬用容器到另一个容器中

    常用查找算法:

    find:按值查找元素,找到返回指定位置迭代器,找不到返回结束迭代器位置

    find_if:按条件查找元素

    adjacent_find:查找相邻重复元素,返回相邻元素的第一个位置的迭代器

    binary_search:查找指定元素是否存在,查到返回true,否则返回false

    count:统计元素个数

    count_if:按条件统计元素个数

    常用排序算法:

    sort:对容器内部进行排序

    random_shuffle:洗牌打乱顺序,指定范围内的元素随机调整次序

    merge:两个容器元素合并,并存储到另一个容器中

    reverse:将容器内元素进行反转

    常用的拷贝和替换算法:

    copy:容器内指定元素拷贝到另一容器

    replace:将容器指定范围内的旧元素修改为新元素

    replace-if:将区间内满足条件的元素,替换成指定元素

    swap:互换两个同种类型容器的元素

    常用的算数生成算法:

    accumulate(求累加):将它的一个内部变量设置为指定的初始值,然后在此初值上累加输入范围内所有元素的值

    fill:对容器实现指定元素的填充

    常用的集合算法:

    set_intersection:求两个集合的交集,源容器必须有序,目标容器开辟取两个源容器较小的

    set_union:求两个集合的并集,源容器必须有序,目标容器开辟取两个源容器之和

    set_difference:求两个集合的差集,源容器必须有序,目标容器开辟取两个源容器较大的


    STL常用算法概述:

    1. 算法主要是由头文件 组成

    2. 是所有STL头文件中最大的一个,范围涉及到比较、交换、查找、遍历、赋值、修改等等

    3. 定义了一些模板类。用以声明函数对象

    4. 体积很小,只包括几个在序列上面进行简单教学运算的模板函数

    常用遍历算法:

    for_each:遍历容器元素

    函数原型:for_each(iterator beg,iterator end, _func);

    beg开始迭代器

    end结束迭代器

    _func函数或者函数对象

    1. void show(string a)//利用函数
    2. {
    3. cout << a << " " << endl;
    4. }
    5. class A { //利用函数对象
    6. public:
    7. void operator ()(string a)
    8. {
    9. cout << a << " " << endl;
    10. }
    11. };
    12. int main()
    13. {
    14. vector vv{ "OK","张三","李四" };
    15. for_each(vv.begin(), vv.end(), show);
    16. cout << "---------------" << endl;
    17. for_each(vv.begin(), vv.end(),A());
    18. return 0;
    19. }

    transform:搬用容器到另一个容器中

    函数原型:for_each(iterator beg1,iterator end1,interator beg2 ,_func);

    beg1源开始迭代器

    end1源结束迭代器

    beg2目标容器开始迭代器

    _func函数或者函数对象 

    1. void show(int a)
    2. {
    3. cout << a << " " << endl;
    4. }
    5. class TT{
    6. public:
    7. int operator ()(int a)
    8. {
    9. return a;
    10. }
    11. };
    12. int ok(int a)
    13. {
    14. return a + 100;
    15. }
    16. int main()
    17. {
    18. vector<int> vv;//源容器
    19. for (int i = 0; i < 10; ++i)
    20. {
    21. vv.push_back(i + 1);
    22. }
    23. vector<int> vg;//目标容器 这样构造没有容量
    24. vg.resize(vv.size());//目标容器需要开辟空间
    25. //正常的搬运 利用函数对象方式
    26. transform(vv.begin(), vv.end(), vg.begin(), TT());
    27. for_each(vg.begin(), vg.end(), show);
    28. cout << "------------------------" << endl;
    29. //边搬运边计算,因此要重写相对应的逻辑函数或者函数对象
    30. transform(vv.begin(), vv.end(), vg.begin(), ok);//利用函数
    31. for_each(vg.begin(), vg.end(), show);
    32. return 0;
    33. }

    常用查找算法:

    find:按值查找元素,找到返回指定位置迭代器,找不到返回结束迭代器位置

    函数原型:find(iterator beg,iterator end,value);

    beg开始迭代器

    end结束迭代器

    value所要查找的元素

    1. class TT{
    2. private:
    3. string name;
    4. int age;
    5. public:
    6. TT(string name, int age) :name(name), age(age) {
    7. }
    8. string Getname(){
    9. return this->name;
    10. }
    11. int Getage() {
    12. return this->age;
    13. }
    14. //重载== 让底层find如何对比自定义数据类型
    15. bool operator==(const TT& t)
    16. {
    17. if (this->name == t.name && this->age == t.age)
    18. {
    19. return true;
    20. }
    21. else
    22. return false;
    23. }
    24. };
    25. int main()
    26. {
    27. vector vv{ {"aa",3},{"bb",4},{"cc",5} };
    28. TT pp("cc", 5);
    29. auto it = find(vv.begin(), vv.end(),pp);
    30. if (it == vv.end())
    31. {
    32. cout << "没有找到" << endl;
    33. }
    34. else
    35. cout << "找到了" << it->Getname()<<" "<Getage()<
    36. return 0;
    37. }

    find_if:按条件查找元素

    函数原型:find(iterator beg,iterator end,pred);

    beg开始迭代器

    end结束迭代器

    pred函数或者谓词(返回bool类型的仿函数)

    1. class TT{
    2. private:
    3. string name;
    4. int age;
    5. public:
    6. TT(string name, int age) :name(name), age(age) {
    7. }
    8. string Getname()const{
    9. return this->name;
    10. }
    11. int Getage()const {
    12. return this->age;
    13. }
    14. };
    15. //函数对象找age大于3的人
    16. class AA {
    17. public:
    18. bool operator()( const TT& t)
    19. {
    20. if (t.Getage() > 3)
    21. {
    22. return true;
    23. }
    24. else
    25. return false;
    26. }
    27. };
    28. int main()
    29. {
    30. vector vv{ {"aa",3},{"bb",4},{"cc",5} };
    31. auto it = find_if(vv.begin(), vv.end(),AA());
    32. for(;it != vv.end();it++)
    33. {
    34. if(it == vv.end())
    35. {
    36. cout << "没有找到" << endl;
    37. }
    38. else
    39. cout << "找到了" << it->Getname()<<" "<Getage()<
    40. }
    41. return 0;
    42. }

    adjacent_find:查找相邻重复元素,返回相邻元素的第一个位置的迭代器

    函数原型:adjacent_find(interator beg,interator end)

    beg开始迭代器

    end结束迭代器

    1. int main()
    2. {
    3. vector<int> vv{1,2,3,4,5,5,6 };
    4. auto it = adjacent_find(vv.begin(), vv.end());
    5. if(it == vv.end())
    6. {
    7. cout << "没有找到" << endl;
    8. }
    9. else
    10. cout << "找到了" <<*it<
    11. return 0;
    12. }

    binary_search:查找指定元素是否存在,查到返回true,否则返回false

    函数原型:bool binary_serach(interator beg,interator end,value)

    注意:在无序序列中不可用

    beg开始迭代器

    end结束迭代器

    value所要查找的元素

    1. int main()
    2. {
    3. vector<int> vv{1,2,3,4,5,5,6 };
    4. if (binary_search(vv.begin(), vv.end(), 7) == 1)
    5. cout << "找到了" << endl;
    6. else
    7. cout << "没有找到" << endl;
    8. return 0;
    9. }

    count:统计元素个数

    函数原型:count(interator beg,interator end,value)

    beg开始迭代器

    end结束迭代器

    value所要查找的元素

    1. class TT {
    2. public:
    3. string name;
    4. int age;
    5. TT(string name, int age) :name(name), age(age) {
    6. }
    7. bool operator==(const TT& t)
    8. {
    9. if (name == t.name && age == t.age)
    10. {
    11. return true;
    12. }
    13. else
    14. return false;
    15. }//统计自定义数据类型时候需要配合重载的operator==
    16. };
    17. int main()
    18. {
    19. vector<int> vv{1,2,3,4,5,5,6 };
    20. int n = count(vv.begin(), vv.end(), 5);//统计5出现的次数
    21. cout << n << endl;
    22. vector vm{ {"刘备",3},{"张飞",4} };
    23. TT t1{ "张飞",4 };
    24. int m = count(vm.begin(), vm.end(), t1);
    25. cout << m << endl;
    26. return 0;
    27. }

    count_if:按条件统计元素个数

    1. 函数原型:count_if(interator beg,interator end,pred)
    2. beg开始迭代器
    3. end结束迭代器
    4. pred条件谓词(bool仿函数)
    1. class TT {
    2. public:
    3. string name;
    4. int age;
    5. TT(string name, int age) :name(name), age(age) {
    6. }
    7. };
    8. class AA {
    9. public:
    10. bool operator()(const TT& t)
    11. {
    12. if (t.age > 1)//统计年龄大于1的
    13. return true;
    14. else
    15. return false;
    16. }
    17. };
    18. class BB {
    19. public:
    20. bool operator()(int b)
    21. {
    22. return b > 2;
    23. }
    24. };
    25. int main()
    26. {
    27. vector<int> vv{1,2,3,4,5,5,6 };
    28. int n = count_if(vv.begin(), vv.end(), BB());//统计大于2的个数
    29. cout << n << endl;
    30. vector vm{ {"刘备",3},{"张飞",4} };
    31. int m = count_if(vm.begin(), vm.end(), AA());//统计年龄大于1的
    32. cout << "年龄大于1的人有:" << m <
    33. return 0;
    34. }

    常用排序算法:

    sort:对容器内部进行排序

    函数原型:sort(interator beg,interator end,pred)

    beg开始迭代器

    end结束迭代器

    pred条件谓词(bool仿函数)

    1. void mprint(int a)
    2. {
    3. cout << a << " ";
    4. }
    5. int main()
    6. {
    7. vector<int> vv{1,3,10,11,2,4,5,3,4,5,4 };
    8. sort(vv.begin(), vv.end());//默认升序
    9. for (int i = 0; i < vv.size(); ++i)
    10. {
    11. cout << vv[i] << " ";
    12. }
    13. cout << endl;
    14. //改为升序,利用STL内置的仿函数
    15. sort(vv.begin(), vv.end(),greater<>());
    16. //利用for_each打印
    17. for_each(vv.begin(), vv.end(), mprint);
    18. return 0;
    19. }

    random_shuffle:洗牌打乱顺序,指定范围内的元素随机调整次序

    函数原型:random_shuffle(interator beg,interator end)

    beg开始迭代器

    end结束迭代器

    1. void mprint(int a)
    2. {
    3. cout << a << " ";
    4. }
    5. int main()
    6. {
    7. srand((unsigned int)time(NULL));
    8. vector<int> vv{1,2,3,4,5,6,7,8 };
    9. //利用洗牌算法打乱顺序,但是每次打乱结果都是一样的
    10. //如果需要真的随机,那就需要添加随机种子
    11. random_shuffle(vv.begin(), vv.end());
    12. for_each(vv.begin(), vv.end(), mprint);
    13. return 0;
    14. }

    merge:两个容器元素合并,并存储到另一个容器中

    注意:两个容器必须是有序的,且合并之后同样有序

    函数原型:merge(interator beg1,interator end1,interator beg2,interator end2,interator dest)

    beg1 容器1开始迭代器

    end1 容器1结束迭代器

    beg2 容器2开始迭代器

    end2 容器2结束迭代器

    dest 目标容器开始迭代器

    1. void mprint(int a)
    2. {
    3. cout << a << " ";
    4. }
    5. int main()
    6. {
    7. vector<int> vv{1,2,3,4,5,6,7,8 };//源容器1
    8. vector<int> vm{ 2,4,5,8 ,10,14,25};//源容器2
    9. vector<int> vx;//目标容器
    10. vx.resize(vv.size() + vm.size());//分配空间
    11. merge(vv.begin(), vv.end(), vm.begin(), vm.end(), vx.begin());
    12. for_each(vx.begin(), vx.end(), mprint);
    13. return 0;
    14. }

    reverse:将容器内元素进行反转

    函数原型:reverse(interator beg,interator end)

    beg开始迭代器

    end结束迭代器

    1. void mprint(int a)
    2. {
    3. cout << a << " ";
    4. }
    5. int main()
    6. {
    7. vector<int> vv{1,2,3,4,5,6,7,8 };//源容器1
    8. cout << "反转前:" << endl;
    9. for_each(vv.begin(), vv.end(), mprint);
    10. cout << endl;
    11. cout << "反转后:" << endl;
    12. reverse(vv.begin(), vv.end());
    13. for_each(vv.begin(), vv.end(), mprint);
    14. return 0;
    15. }

    常用的拷贝和替换算法:

    copy:容器内指定元素拷贝到另一容器

    函数原型:copy(interator beg,interator end,interator dest)

    beg源容器开始迭代器

    end源容器结束迭代器

    dest目标容器开始拷贝位置的迭代器

    1. void mprint(int a)
    2. {
    3. cout << a << " ";
    4. }
    5. int main()
    6. {
    7. vector<int> vv{1,2,3,4,5,6,7,8 };//源容器
    8. vector<int>vx(15, 2);//目标容器
    9. //开辟了15 个2 ,源容器元素少拷贝到目标容器后
    10. //前面的元素改变,后面依然是2
    11. //如果目标容器容量小或者没有,需要申请容量
    12. copy(vv.begin(), vv.end(), vx.begin());
    13. for_each(vx.begin(), vx.end(), mprint);
    14. return 0;
    15. }

    replace:将容器指定范围内的旧元素修改为新元素

    replace(interator beg,interator end,oldvalue,newvalue)

    beg开始迭代器

    end结束迭代器

    oldvalue旧元素

    newvalue新元素

    1. int main()
    2. {
    3. vector<int> vv{1,2,5,5,4,5,5,6,7,8 };
    4. replace(vv.begin() + 2, vv.end(), 5, 50);
    5. //将2下标到end区间的5都换成50 ,begin和end是左闭右开的区间
    6. for (auto it = vv.begin(); it != vv.end(); it++)
    7. {
    8. cout << (*it) << " ";
    9. }
    10. return 0;
    11. }

    replace-if:将区间内满足条件的元素,替换成指定元素

    replace_if(interator beg,interator end,pred,newvalue)

    beg开始迭代器

    end结束迭代器

    pred 谓词

    newvalue替换的新元素

    1. class Pred { //仿函数
    2. public:
    3. bool operator()(string name)
    4. {
    5. return name == "张三";
    6. }
    7. };
    8. bool AA(string name)//普通自定义函数
    9. {
    10. return name == "张三";
    11. }
    12. int main()
    13. {
    14. vectorvv;
    15. vv.push_back("张三");
    16. vv.push_back("李四");
    17. vv.push_back("张三");
    18. vv.push_back("李四");
    19. vv.push_back("张三");
    20. //将张三全部替换为王五
    21. replace_if(vv.begin(), vv.end(), Pred(), "王五");//调用的仿函数,也可以调用普通函数AA
    22. for (auto it = vv.begin(); it != vv.end(); it++)
    23. {
    24. cout << (*it) << " ";
    25. }
    26. return 0;
    27. }

    swap:互换两个同种类型容器的元素

    swap(container c1 ,container c2);

    c1 容器

    c2容器

    1. void show(vector<int>&v1)
    2. {
    3. for (auto it = v1.begin(); it != v1.end(); it++)
    4. {
    5. cout << (*it) << " ";
    6. }
    7. cout << endl;
    8. }
    9. int main()
    10. {
    11. vector<int>v1{5,5,1,2,4,5};
    12. vector<int>v2{ 1,2,3,4,5,6,7,8,9,10 };
    13. cout << "v1交换前:" << endl;
    14. show(v1);
    15. cout << "v2交换前:" << endl;
    16. show(v2);
    17. cout << "------------------------------" << endl;
    18. swap(v1, v2);
    19. // v1.swap(v2);使用vector内置的swap交换
    20. cout << "v1交换后:" << endl;
    21. show(v1);
    22. cout << "v2交换后:" << endl;
    23. show(v2);
    24. }

    常用的算数生成算法:

    accumulate(求累加):将它的一个内部变量设置为指定的初始值,然后在此初值上累加输入范围内所有元素的值

    函数原型:accumulate(interator beg,interator end,value);

    beg 开始迭代器

    end 结束迭代器

    value 和的起始值

    1. int main()
    2. {
    3. vector<int>vv{ 1,2,3,4,5,6,7,8,9,10 };
    4. int n = accumulate(vv.begin(), vv.end(),100);
    5. cout << n << endl;//155,因为内部起始值设置的是100
    6. return 0;
    7. }

    fill:对容器实现指定元素的填充

    函数原型:fill(interator beg,interator end,value);

    beg 开始迭代器

    end 结束迭代器

    value 填充的值

    1. void show(vector<int>&v1)
    2. {
    3. for (auto it = v1.begin(); it != v1.end(); it++)
    4. {
    5. cout << (*it) << " ";
    6. }
    7. cout << endl;
    8. }
    9. int main()
    10. {
    11. vector<int>vv(10, 1);//初始化10个1
    12. fill(vv.begin(), vv.begin() + 5, 2);//前5个填充为2
    13. show(vv);
    14. return 0;
    15. }

    常用的集合算法:

    set_intersection:求两个集合的交集,源容器必须有序,目标容器开辟取两个源容器较小的

    函数原型:set_intersection(interator beg1,interator end1,interator beg2,interator end2,interator dest)

    beg1容器1的开始迭代器

    end1容器1的结束迭代器

    beg2容器2的开始迭代器

    end2容器2的结束迭代器

    dest目标容器的开始迭代器

    set_union

    1. void show(vector<int>&v1)
    2. {
    3. for (auto it = v1.begin(); it != v1.end(); it++)
    4. {
    5. cout << (*it) << " ";
    6. }
    7. cout << endl;
    8. }
    9. int main()
    10. {
    11. vector<int>vv{ 0,1,2,3,4,5,6,7,8,9 };//容器1
    12. vector<int>vvm{ 6,7,8,9,10,11,12 };//容器2
    13. vector<int>vmx;//目标容器
    14. vmx.resize(min(vv.size(),vvm.size()));//开辟空间,取小容器大小
    15. set_intersection(vv.begin(), vv.end(), vvm.begin(), vvm.end(), vmx.begin());
    16. show(vmx);//会遍历所有数据将交集数据以及后面申请空间默认的0都打印出来
    17. //6 7 8 9 0 0 0
    18. //返回交集结束的迭代器
    19. auto is= set_intersection(vv.begin(), vv.end(), vvm.begin(), vvm.end(), vmx.begin());
    20. //输出
    21. for (auto im=vmx.begin();im!=is;im++)
    22. {
    23. cout << (*im) << " ";//6 7 8 9
    24. }
    25. return 0;
    26. }

    set_union:求两个集合的并集,源容器必须有序,目标容器开辟取两个源容器之和

    函数原型:set_union(interator beg1,interator end1,interator beg2,interator end2,interator dest)

    beg1容器1的开始迭代器

    end1容器1的结束迭代器

    beg2容器2的开始迭代器

    end2容器2的结束迭代器

    dest目标容器的开始迭代器

    1. void show(vector<int>&v1)
    2. {
    3. for (auto it = v1.begin(); it != v1.end(); it++)
    4. {
    5. cout << (*it) << " ";
    6. }
    7. cout << endl;
    8. }
    9. int main()
    10. {
    11. vector<int>vv{ 1,2,3,4,4,5,6,7,7};//容器1
    12. vector<int>vvm{ 6,7,8,9,10,11,12 };//容器2
    13. vector<int>vmx;//目标容器
    14. vmx.resize(vv.size()+vvm.size());
    15. set_union(vv.begin(), vv.end(), vvm.begin(), vvm.end(), vmx.begin());
    16. show(vmx);//会遍历所有数据将并集数据以及(如果空间有剩余)后面申请空间默认的0都打印出来
    17. //返回并集结束的迭代器
    18. auto is= set_union(vv.begin(), vv.end(), vvm.begin(), vvm.end(), vmx.begin());
    19. //输出
    20. for (auto im=vmx.begin();im!=is;im++)
    21. {
    22. cout << (*im) << " ";
    23. }
    24. return 0;
    25. }

    set_difference:求两个集合的差集,源容器必须有序,目标容器开辟取两个源容器较大的

    函数原型:set_difference(interator beg1,interator end1,interator beg2,interator end2,interator dest)

    beg1容器1的开始迭代器

    end1容器1的结束迭代器

    beg2容器2的开始迭代器

    end2容器2的结束迭代器

    dest目标容器的开始迭代器

    1. void show(vector<int>&v1)
    2. {
    3. for (auto it = v1.begin(); it != v1.end(); it++)
    4. {
    5. cout << (*it) << " ";
    6. }
    7. cout << endl;
    8. }
    9. int main()
    10. {
    11. vector<int>vv{ 1,2,3,4,4,5,6,7,7};//容器1
    12. vector<int>vvm{ 6,7,8,9,10,11,12 };//容器2
    13. vector<int>vmx;//目标容器
    14. vmx.resize(max(vv.size(),vvm.size()));//最特殊的情况取最大的
    15. set_difference(vv.begin(), vv.end(), vvm.begin(), vvm.end(), vmx.begin());
    16. show(vmx);//会遍历所有数据将差集数据以及(如果空间有剩余)后面申请空间默认的0都打印出来
    17. //返回并集结束的迭代器
    18. auto is= set_difference(vv.begin(), vv.end(), vvm.begin(), vvm.end(), vmx.begin());
    19. //输出
    20. for (auto im=vmx.begin();im!=is;im++)
    21. {
    22. cout << (*im) << " ";
    23. }
    24. return 0;
    25. }

    STL系列基础更新到这里就结束了,有兴趣订阅专栏,收藏学习。

  • 相关阅读:
    探索流视频的发送
    前端程序员的职业规格
    conda虚拟环境中安装的cuda和服务器上安装的cuda的异同
    Tomcat 提高 I/O性能的秘密—— AprEndpoint 组件
    SpringCloudAlibaba【四】Nacos Config 多环境切换与公共配置
    计算机保研,maybe this is all you need(普通双非学子上岸浙大工程师数据科学项目)
    Python机器学习实战-建立Gradient Boosting模型预测肾脏疾病(附源码和实现效果)
    ubuntu安装nps客户端
    C#应用程序界面开发基础——窗体控制
    【数据库系统概论】数据库系统外部的体系结构
  • 原文地址:https://blog.csdn.net/weixin_51609435/article/details/126334463