• Day 21:C++STL算法篇(2/2)


    目录

    一、STL排列组合算法

            1.什么是上(下一个排序组合)?

             2.两个方法:(会改变原容器的顺序!)

                    ①next_permutation

                    ②prev_permutation

            3.实际应用库举例:

    二、STL 算术算法

             1.accumulate:区间求和

            2.partial_sum:相邻元素的和,逐步求和。

            3.inner_product:序列内积运算

            4.adjacent_difference: 求相邻元素

    三、STL 生成异变算法

            1.for_each:迭代访问

            2.有关fill        

                    ①fill:填充方式初始容器

                    ②fill_n:指定长度填充容器

            3.有关generate

                    ①generate:填充容器

                    ②generate_n:填充前n个位置

            4.transform:一元转换和二元转换

    四、STL 关系算法

            1.equal:两容器元素是否都相同(顺序也要是相同的)

            2.includes:是否是包含关系(必须要是有序容器)

            3.lexicographical_compare:比较两个序列(类似于string的比较。)

            4.求max

                    ①max:求最大值

                    ②max_element:返回最大值的iterator

            5.求min,原理同max,在此不过多赘述

            6.mismatch:找到第一个不同的位置

    五、STL集合算法

    set_union:差集(&)

    set_intersection:并集(|)

    set_difference:差集(相对差-)

    set_symmetric_difference:对称差集(^)

    六、STL堆算法

            1.是什么堆?:

            2.大顶堆:

            3常用函数.        

                    ①make_heap:生成一个堆

                    ②pop_heap:出堆

                    ③push_heap:入堆

                    ④sort_heap:堆排序


    一、STL排列组合算法

            1.什么是上(下一个排序组合)?

             2.两个方法:(会改变原容器的顺序!)

                    ①next_permutation

                            下一个排序序列的组合(返回值:bool类型,有就返回true,无则返回false)->(有序组合后的)数字越来越大

                    ②prev_permutation

                            上一个排序序列的组合->数字越来越小

    1. array<int, 3> data = { 1,2,3 };//123
    2. next_permutation(data.begin(), data.end());//变大一次->132
    3. for (auto v : data)
    4. {
    5. cout << v;
    6. }
    7. cout << endl;
    8. prev_permutation(data.begin(), data.end());//变小一次->123
    9. for (auto v : data)
    10. {
    11. cout << v;
    12. }

     输出:

    132
    123

            3.实际应用库举例:

                    做算法题的时候,4个数的不重复的组合的all情况(用next则起始数字用1234,用prev则起始数字为4321)

    1. vector<int> vecData = { 1,2,3,4 };
    2. int i = 0;
    3. do
    4. {
    5. cout << "第 " << i + 1 << " 组合结果:";
    6. for (auto v : vecData)
    7. {
    8. cout << v;
    9. }
    10. cout << endl;
    11. i++;
    12. } while (next_permutation(vecData.begin(), vecData.end()));

    输出:

    第 1 组合结果:1234
    第 2 组合结果:1243
    第 3 组合结果:1324
    第 4 组合结果:1342
    第 5 组合结果:1423
    第 6 组合结果:1432
    第 7 组合结果:2134
    第 8 组合结果:2143
    第 9 组合结果:2314
    第 10 组合结果:2341
    第 11 组合结果:2413
    第 12 组合结果:2431
    第 13 组合结果:3124
    第 14 组合结果:3142
    第 15 组合结果:3214
    第 16 组合结果:3241
    第 17 组合结果:3412
    第 18 组合结果:3421
    第 19 组合结果:4123
    第 20 组合结果:4132
    第 21 组合结果:4213
    第 22 组合结果:4231
    第 23 组合结果:4312
    第 24 组合结果:4321

    二、STL 算术算法

    注:做数字操作的头文件<numeric> 以及<iterator>

             1.accumulate:区间求和

                    三个参数->前两个参数:区间的起末,第三个是sum的初值(常为0)

    1. //1.求和
    2. vector<int> data = { 1,2,3,4,5,6,7,8,9 };
    3. int sum = 0;
    4. for (auto v : data)
    5. {
    6. sum += v;
    7. }
    8. cout << sum << endl;
    9. sum = 0;
    10. sum = accumulate(data.begin(), data.end(), 0);
    11. cout << sum << endl;
    12. sum = accumulate(data.begin(), data.end(), 100);
    13. cout << sum << endl;

    输出: 

    45
    45
    145       //第三个参数的起始值改为了100

            2.partial_sum:相邻元素的和,逐步求和。

    1. //2.逐步求和
    2. vector<int> data = { 1,2,3,4,5,6,7,8,9 };
    3. vector<int> result(data.size());
    4. partial_sum(data.begin(), data.end(), result.begin());
    5. for (auto v : result)
    6. {
    7. cout << v<<" ";
    8. }
    9. cout << endl;

     输出:1 3 6 10 15 21 28 36 45 

            3.inner_product:序列内积运算

                    注:必须要满足矩阵的乘法规则,否则会直接报错

    1. //3.求内积运算:矩阵乘法
    2. vector<int> first(4);
    3. vector<int> second(4);
    4. for (int i = 0; i < 4; i++)
    5. {
    6. first[i] = i + 1; //1 2 3 4
    7. second[i] = i + 1; //1 2 3 4
    8. }
    9. cout << inner_product(first.begin(), first.end(), second.begin(), 0) << endl;

     输出:30                                //本处用的是两个向量的内积。

            4.adjacent_difference: 求相邻元素

                      运算方法:当前位置和前一个位置的差值

    1. //4.求差值
    2. vector<int> test = { 2,2,3,4,5,6,7,8,9 };
    3. adjacent_difference(test.begin(), test.end(),
    4. ostream_iterator<int>(cout, "\t"));
    5. cout << endl;
    6. //ostream_iterator<int>(cout, "\t") 新容器开始位置替换这个参数

    输出:2       0       1       1       1       1       1       1       1

                    注意:本处的第三个参数应该是迭代器(正常情况保存的话,可以开一个容器vecData,那么第三个参数可写 vecData.begin()来保存)

                    ->本处(采用流型迭代器!->也是迭代器)是为了直接打印到屏幕上! 

    三、STL 生成异变算法

            1.for_each:迭代访问

                    ->三个参数:起+末+子函数指针(每个元素遍历都分别按子函数进行操作)(三种写法)

    1. //1.for_each遍历
    2. vector<int> testData = { 1,2,3,4,5,6,7,8,9 };
    3. for_each(testData.begin(), testData.end(),
    4. [](int x) {cout << x << "\t"; });
    5. cout << endl;
    6. for_each(testData.begin(), testData.end(),print);
    7. cout << endl;
    8. for_each(testData.begin(), testData.end(),
    9. [](int& x) {x *= 2; cout << x <<"\t"; });
    10. cout << endl;

    输出: 

    1       2       3       4       5       6       7       8       9
    1       2       3       4       5       6       7       8       9
    2       4       6       8       10      12      14      16      18

                    注:此处提供了打印容器的新写法 +函数指针的处理

                            (不一定要是打印,也可以进行其他的操作)

            2.有关fill        

                    ①fill:填充方式初始容器

                            区间填充 参数:起++需要填充的元素

    1. //2.fill
    2. vector<int> fillData(3);
    3. fill(fillData.begin()+2, fillData.end(), 10);
    4. for_each(fillData.begin(), fillData.end(),
    5. [](int x) {cout << x << "\t"; });/*打印容器*/

    输出: 0       0       10

                    ②fill_n:指定长度填充容器

                            区间填充 参数:起+填充个数num+需要填充的元素(更加灵活一点)

    1. //3.fill_n
    2. vector<int> fData(4);
    3. fill_n(fData.begin()+2, 2, 100);
    4. //开始位置,填充几个, 填的元素是什么
    5. for_each(fData.begin(), fData.end(),[](int x){ cout<<x<<"\t";});

     输出:0       0       100     100

            3.有关generate

                    ①generate:填充容器

                            通过函数去复制 参数:起++函数指针

    1. vector<int> gData(4);
    2. generate(gData.begin(), gData.end(),[]() {return 222; });
    3. for_each(gData.begin(), gData.end(),[](int x) {cout << x << "\t"; });
    4. cout << endl;

    输出: 222     222     222     222

                    ②generate_n:填充前n个位置

                            通过函数去复制 参数:起+操作个数num+函数指针

    1. vector<int> gData(4);
    2. generate_n(gData.begin(),2, []() {return 111; });
    3. for_each(gData.begin(), gData.end(), [](int x) {cout << x << "\t"; });

    输出: 111     111     0       0

            4.transform:一元转换和二元转换

                    注:(相对于generate的区别,就是其不会改变原容器的,而是将结果进行另存)

                    参数:起+末+存储容器的起始+处理方式的函数指针

    1. //5.transform
    2. vector<int> testTrans = { 1,2,3,4,5,6,7,8,9 };
    3. vector<int> resultTrans(testTrans.size());
    4. transform(testTrans.begin(), testTrans.end(),
    5. resultTrans.begin(),[](int data) {return -data; });
    6. for_each(resultTrans.begin(), resultTrans.end(), [](int x) {cout << x << "\t"; });
    7. cout << endl;

    输出: -1      -2      -3      -4      -5      -6      -7      -8      -9  

    四、STL 关系算法

            1.equal:两容器元素是否都相同(顺序也要是相同的)

    1. //1.比较
    2. vector<int> one = { 1,2,3,4,5,6,7 };
    3. vector<int> two = { 1,2,3,4,5,7,6 };
    4. cout << boolalpha << equal(one.begin(), one.end(), two.begin()) << endl;

    输出: false                                   //vector中元素顺序不同,则两个容器的元素不相同

            2.includes:是否是包含关系(必须要是有序容器)

                    (四个参数,两个容器的起末区间即可。)

    1. //2.包含关系要是有序
    2. vector<int> one = { 1,2,3,4,5,6,7 };
    3. vector<int> thrid = { 1,2,3};
    4. cout << boolalpha << includes(one.begin(), one.end(),
    5. thrid.begin(),thrid.end()) <<endl;

    输出: true

                    若该容器不是有序的,则会报错!!

             

            3.lexicographical_compare:比较两个序列(类似于string的比较。)

    1. //3.比较 第一个小于第二个就返回true
    2. vector<int> one = { 1,2,3,4,5,6,7 };
    3. vector<int> two = { 1,2,3,4,5,7,6 };
    4. cout << boolalpha << lexicographical_compare(one.begin(), one.end(),
    5. two.begin(), two.end()) << endl;

    输出:true                                 //比较 第一个小于第二个就返回true

            4.求max

                    ①max:求最大值

                            此地无银三百两->此函数不是给iterator设计的,不是区间内的最大值,而是比较两个参数的max值

                    ②max_element:返回最大值的iterator

                            专门用于迭代器->找出这个可迭代容器的中最大值(区间内的最大值)

            5.求min,原理同max,在此不过多赘述

    1. //test for "min" and "max"
    2. vector<int> one = { 1,2,3,4,5,6,7 };
    3. vector<int> two = { 1,2,3,4,5,7,6 };
    4. cout << "max:" << max(1,3) << endl;
    5. cout << "min:" << min(1, 2) << endl;
    6. cout << "Max:" << *max_element(two.begin(), two.end()) << endl;
    7. cout << "Min:" << *min_element(one.begin(), one.end()) << endl;

    输出:

    max:3
    min:1
    Max:7
    Min:1 

            6.mismatch:找到第一个不同的位置

                    返回值:一个指向pair数对类型的迭代器iterator

                    参数:两个容器的起止位置(共四个参数)

    1. //4.找第一个不同地方
    2. vector<int> one = { 1,2,3,4,5,6,7 };
    3. vector<int> two = { 1,2,3,4,5,7,6 };
    4. cout << *mismatch(one.begin(), one.end(), two.begin(), two.end()).first << endl;
    5. cout << *mismatch(one.begin(), one.end(), two.begin(), two.end()).second << endl;
    6. //first: 第一容器不同的元素的位置
    7. //second: 第二个容器不同的元素的位置

    输出: 

    6
    7

    //first: 第一容器不同的元素的位置
    //second: 第二个容器不同的元素的位置 

    五、STL集合算法

    • set_union:差集(&)

    • set_intersection:并集(|)

    • set_difference:差集(相对差-)

    • set_symmetric_difference:对称差集(^)

                    说明:参数均为5个两个容器的起止位置(前4个),最后一个位置存储的位置的迭代器(当你不想保存到某个容器中的时候,可采用下面的流型迭代器写法,直接输出到屏幕上。)

    1. #include <iostream>
    2. #include <algorithm>
    3. #include <functional>
    4. #include <iterator>
    5. #include <vector>
    6. using namespace std;
    7. int main()
    8. {
    9. vector<int> one = { 1,2,3,4,5,6 };
    10. vector<int> two = { 4,5,6,7,8,9 };
    11. vector<int> result(one.size() + two.size());
    12. //1.并集
    13. set_union(one.begin(), one.end(), two.begin(), two.end(),
    14. result.begin());
    15. for_each(result.begin(), result.end(),
    16. [](int x) {if (x != 0) { cout << x << "\t"; }});
    17. cout << endl;
    18. //2.交集
    19. set_intersection(one.begin(), one.end(), two.begin(), two.end(),
    20. ostream_iterator<int>(cout, "\t")
    21. );
    22. cout << endl;
    23. //3.求差集
    24. set_difference(one.begin(), one.end(), two.begin(), two.end(),
    25. ostream_iterator<int>(cout, "\t"));
    26. cout << endl;
    27. //4.对称差集
    28. set_symmetric_difference(one.begin(), one.end(), two.begin(), two.end(),
    29. ostream_iterator<int>(cout, "\t"));
    30. cout << endl;
    31. return 0;
    32. }

    输出:

    1       2       3       4       5       6       7       8       9
    4       5       6
    1       2       3
    1       2       3       7       8       9

    六、STL堆算法

            1.是什么堆?:

                    (一堆数据)一定是一个完全二叉树,放在数组中是无序的,在二叉树中是有序的。

            2.大顶堆:

                    父亲节点要大于子节点(向上渗透)->出堆一定是有序的(大顶堆的出堆方式,从大到小出来。小顶堆相反)

            3常用函数.        

                    ①make_heap:生成一个堆

                            (默认是大顶堆,默认的第三参数是计算准则less<int>->可缺省)->所以greater<int>是小顶堆

                            :此处准则一定要和sort_heap的堆排序准则一致!!!!否则报错

                            make_heap之后容器中元素的顺序就会改变(按照二叉树的方式进行排序!)

                    ②pop_heap:出堆

                            把要出堆的元素放到容器的绒面,并没有真正的删除需要手动调用容器的删除函数进行删除

                    ③push_heap:入堆

                    ④sort_heap:堆排序

                            ->改变存储的容器中元素顺序  (但更常用的是popheap结合vector的pop_back方法)

    1. #include <iostream>
    2. #include <algorithm>
    3. #include <string>
    4. #include <vector>
    5. #include <functional>
    6. using namespace std;
    7. int main()
    8. {
    9. vector<int> data = { 1,3,19,9,4,7 };
    10. make_heap(data.begin(), data.end()); //默认形式是大顶堆
    11. for (auto v : data)
    12. {
    13. cout << v << "\t";
    14. }
    15. cout << endl;
    16. cout << "出堆:" << endl;
    17. while (!data.empty())
    18. {
    19. pop_heap(data.begin(), data.end()); //要出去的元素放到最后面
    20. cout << data.back() << "\t";
    21. data.pop_back(); //真正的删除元素
    22. }
    23. cout << endl;
    24. vector<int> data2 = { 1,3,19,9,4,7 };
    25. //less方式是大顶堆,和默认是一样的
    26. make_heap(data2.begin(), data2.end(), less<int>());
    27. //sort_heap(data2.begin(), data2.end(), greater<int>());
    28. //上面一句 会报错,堆排序准则一定要和生成准则一致
    29. vector<int> data3 = { 1,3,19,9,4,7 };
    30. make_heap(data3.begin(), data3.end(), greater<int>());
    31. sort_heap(data3.begin(), data3.end(), greater<int>());
    32. for (auto v : data3)
    33. {
    34. cout << v << "\t";
    35. }
    36. cout << endl;
    37. return 0;
    38. }

     输出:

    19      9       7       3       4       1
    出堆:
    19      9       7       4       3       1
    19      9       7       4       3       1

  • 相关阅读:
    Linux下路由表的转发流程
    el-table的一些样式总结
    关于CLR GC调优的一些问题
    初探 Vue3 新特性
    Java分库分表配置
    你写过的最蠢的代码是?
    NIO知识总结三
    【计算机网络】子网掩码、子网划分
    AM@由极限的两个存在准则(定理)推导的两个重要极限
    【暑期每日一题】洛谷 P7257 [COCI2009-2010#3] FILIP
  • 原文地址:https://blog.csdn.net/zjjaibc/article/details/125557642