【STL终极奥义❀解耦合思想的实现❀】函数对象、谓词与函数适配器——从for_each、transform、count_if、sort算法源码的角度分析(三)

简介: 【STL终极奥义❀解耦合思想的实现❀】函数对象、谓词与函数适配器——从for_each、transform、count_if、sort算法源码的角度分析

三、STL提供的统一性思考

算法的统一性延伸至STL的统一性思考

1. _OutIt transform(const _InIt _First, const _InIt _Last, _OutIt _Dest, _Fn _Func)
2. _OutIt transform(const _InIt1 _First1, const _InIt1 _Last1, const _InIt2 _First2, _OutIt _Dest, _Fn _Func)
3. //_First1 : 容器1的输入迭代器begin()   _Last1 : 容器1的输入迭代器end()
4. //_First2 : 容器2的输入迭代器begin()
5. //_Dest : 输出迭代器
6. //_Func : 函数对象/回调函数
7. //算法的核心思想:
8. //transform提供了一个统一的操作,把容器1和容器2的元素当作输入,把操作结果放到容器3中
9. //容器中的元素遍历由迭代器提供
10. //容器1和容器2之间的操作由函数对象提供
11. //通过算法实现了数据类型和具体算法的分离
12. //transform只提供一个把容器1和容器2的元素运算后放入容器3这个统一模型,这个算法是通用的
13. //而具体的算法,是加减乘除还是其他运算由函数对象来提供(由我们自己编写)
14. //输入输出的数据类型由容器来决定,容器和算法之间通过迭代器连接
15. 
16. //容器实现了数据类型和容器本身的分离,比如我们通过vector可以放入int\string\class等
17. //容器提供了统一的一个模型,里面的元素只是元素本身,不用管是什么类型,他就是一个元素
18. 
19. //迭代器提供了遍历容器的统一方法,不管什么容器vector\deque\queue\set\map,也不管
20. //容器中装的什么元素int\string\class,都可以使用迭代器进行遍历,迭代器总是指向容器中的一个元素
21. //迭代器这种统一的遍历方法为算法的统一性提供了基础
22. 
23. //算法提供了算法本身的统一性,算法本身提供一个模型,具体操作由函数对象\回调函数提供
24. //回调函数实现了任务实现与任务调用的分离
25. //容器和算法之间由迭代器提连接的桥梁


🧧附:完整代码🧧

1. #include <iostream>
2. using namespace std;
3. 
4. #include <vector>
5. #include <string>
6. #include <algorithm> //使用算法
7. #include <functional> //使用预定义函数对象和适配器
8. 
9. //一元函数对象
10. template<typename _MyType>
11. class _FroEachClass
12. {
13. public:
14.   void operator()(_MyType& t)
15.   {
16.     cout << t << " ";
17.     m_count++;
18.   }
19. public:
20.   _FroEachClass()
21.   {
22.     this->m_count = 0;
23.   }
24. public:
25.   int get_count()
26.   {
27.     return this->m_count;
28.   }
29. private:
30.   int m_count;
31. };
32. 
33. template<typename _MyType>
34. void _FroEachFunc(_MyType& t)
35. {
36.   cout << t << " ";
37. }
38. 
39. //一元谓词
40. template<typename _MyType>
41. class _CountOfClass
42. {
43. public:
44.   bool operator()(_MyType& t)
45.   {
46.     return (t == this->m_data);
47.   }
48. public:
49.   _CountOfClass(_MyType& t)
50.   {
51.     this->m_data = t;
52.   }
53. private:
54.   _MyType m_data;
55. };
56. 
57. template<typename _MyType>
58. bool _CountOfFunc(_MyType& t1)
59. {
60.   string s = "!";
61.   return (t1 == s);
62. }
63. 
64. //二元函数对象
65. template<typename _MyType>
66. class _TransformClass
67. {
68. public:
69.   _MyType operator()(_MyType& t1, _MyType& t2)
70.   {
71.     return (t1 + t2);
72.   }
73. };
74. 
75. template<typename _MyType>
76. _MyType _TransformFunc(_MyType& t1, _MyType& t2)
77. {
78.   return (t1 + t2);
79. }
80. 
81. //二元谓词
82. template<typename _MyType>
83. class _SortClass
84. {
85. public:
86.   bool operator()(_MyType& t1, _MyType& t2)
87.   {
88.     return (t1 > t2);
89.   }
90. };
91. 
92. template<typename _MyType>
93. bool _SortFunc(_MyType& t1, _MyType& t2)
94. {
95.   return (t1 > t2);
96. }
97. 
98. int main()
99. {
100.  vector<string> v1;
101.  v1.push_back("hello");
102.  v1.push_back("C++");
103.  v1.push_back("STL");
104.  v1.push_back("!");
105.  v1.push_back("!");
106.  v1.push_back("!");
107. 
108.  /*
109.  _Fn for_each(_InIt _First, _InIt _Last, _Fn _Func) { // perform function for each element [_First, _Last)
110.    _Adl_verify_range(_First, _Last);
111.    auto _UFirst = _Get_unwrapped(_First);
112.    const auto _ULast = _Get_unwrapped(_Last);
113.    for (; _UFirst != _ULast; ++_UFirst) {
114.      _Func(*_UFirst); //通过源码可知,for_each 的函数对象是一元函数对象
115.    }
116. 
117.    return _Func;
118.  }
119.  */
120.  //通过 for_each 算法实现遍历容器  --- 使用一元函数对象
121.  _FroEachClass<string> for_each_obj;
122.  for_each_obj = for_each(v1.begin(), v1.end(), for_each_obj);
123.  cout << "\nvector size: " << for_each_obj.get_count() << endl;
124.  for_each(v1.begin(), v1.end(), _FroEachFunc<string>);
125.  cout << endl;
126. 
127.  /*
128.  template <class _InIt, class _Pr>
129.  _NODISCARD _Iter_diff_t<_InIt> count_if(_InIt _First, _InIt _Last, _Pr _Pred) { // count elements satisfying _Pred
130.    _Adl_verify_range(_First, _Last);
131.    auto _UFirst = _Get_unwrapped(_First);
132.    const auto _ULast = _Get_unwrapped(_Last);
133.    _Iter_diff_t<_InIt> _Count = 0;
134.    for (; _UFirst != _ULast; ++_UFirst) {
135.      if (_Pred(*_UFirst)) { //由此可见_Pred返回的应该是一个bool
136.        ++_Count;
137.      }
138.    }
139. 
140.    return _Count;
141.  }
142.  */
143.  //用count_if计算 某个元素的个数  ---  使用一元谓词
144.  string s("!");
145.  int count = count_if(v1.begin(), v1.end(), _CountOfClass<string>(s));
146.  cout << "count : " << count << endl;
147.  count = count_if(v1.begin(), v1.end(), _CountOfFunc<string>); //使用回调函数也可以编译通过
148.  cout << "count : " << count << endl;
149. 
150.  /*
151.  template <class _InIt1, class _InIt2, class _OutIt, class _Fn>
152.  _OutIt transform(const _InIt1 _First1, const _InIt1 _Last1, const _InIt2 _First2, _OutIt _Dest, _Fn _Func) {
153.    // transform [_First1, _Last1) and [_First2, ...) with _Func
154.    _Adl_verify_range(_First1, _Last1);
155.    auto _UFirst1 = _Get_unwrapped(_First1);
156.    const auto _ULast1 = _Get_unwrapped(_Last1);
157.    const auto _Count = _Idl_distance<_InIt1>(_UFirst1, _ULast1);
158.    auto _UFirst2 = _Get_unwrapped_n(_First2, _Count);
159.    auto _UDest = _Get_unwrapped_n(_Dest, _Count);
160.    for (; _UFirst1 != _ULast1; ++_UFirst1, (void) ++_UFirst2, ++_UDest) {
161.      *_UDest = _Func(*_UFirst1, *_UFirst2); //把两个参数_UFirst1和_UFirst2的元素传入_Func返回结果放入_UDest
162.    }
163. 
164.    _Seek_wrapped(_Dest, _UDest);
165.    return _Dest;
166.  }
167.  */
168.  //用transform把两个容器内容相加放入第三个容器  ---  使用二元函数对象
169.  vector<string> v3(for_each_obj.get_count() + 1);
170.  v3[6] = "end";
171.  transform(v1.begin(), v1.end(), v1.begin(), v3.begin(), _TransformClass<string>());
172.  for_each(v3.begin(), v3.end(), _FroEachClass<string>());
173.  cout << endl;
174.  vector<string>::iterator it = transform(v1.begin(), v1.end(), v1.begin(), v3.begin(), _TransformFunc<string>);
175.  for_each(v3.begin(), v3.end(), _FroEachClass<string>());
176.  cout << endl;
177.  cout << *it << endl; //transform 返回的是: v1 + v2 最后一个元素相加后,后面的那个位置的迭代器
178. 
179.  /*
180.  template <class _RanIt, class _Pr>
181.  void sort(const _RanIt _First, const _RanIt _Last, _Pr _Pred) { // order [_First, _Last), using _Pred
182.    _Adl_verify_range(_First, _Last);
183.    const auto _UFirst = _Get_unwrapped(_First);
184.    const auto _ULast = _Get_unwrapped(_Last);
185.    _Sort_unchecked(_UFirst, _ULast, _ULast - _UFirst, _Pass_fn(_Pred));
186.  }
187.  */
188.  //用sort算法实现排序,使用二元谓词
189.  vector<int> v4;
190.  for (int i = 0; i < 10; i++)
191.  {
192.    //v4.push_back(rand());
193.    v4.push_back(i + 1);
194.  }
195.  v4.push_back(1);
196.  sort(v4.begin(), v4.end(), _SortClass<int>());
197.  for_each(v4.begin(), v4.end(), _FroEachClass<int>());
198.  cout << endl;
199.  sort(v4.begin(), v4.end(), _SortFunc<int>);
200.  for_each(v4.begin(), v4.end(), _FroEachClass<int>());
201.  cout << endl;
202.  sort(v4.begin(), v4.end(), greater<int>()); //使用预定义函数对象
203.  for_each(v4.begin(), v4.end(), _FroEachClass<int>());
204.  cout << endl;
205. 
206.  //使用 count_if 计算大于5的元素的个数
207.  int n = 5;
208.  int num = count_if(v4.begin(), v4.end(), bind2nd(greater<int>(), n));
209.  //count_if 接收一元函数对象或一元谓词,我们借用二元谓词greater实现计算大于5的元素个数
210.  //这时可以使用绑定器 bind2nd 把预定义函数对象greater和一个参数n适配为一元谓词
211.  cout << "greater " << n << " : " << num << endl;
212. 
213.  system("pause");
214.  return 0;
215. }
相关文章
|
4天前
|
机器学习/深度学习 自然语言处理 算法
Python遗传算法GA对长短期记忆LSTM深度学习模型超参数调优分析司机数据|附数据代码
Python遗传算法GA对长短期记忆LSTM深度学习模型超参数调优分析司机数据|附数据代码
|
11天前
|
机器学习/深度学习 算法 数据可视化
Matlab决策树、模糊C-均值聚类算法分析高校教师职称学历评分可视化
Matlab决策树、模糊C-均值聚类算法分析高校教师职称学历评分可视化
|
12天前
|
算法 搜索推荐 数据挖掘
MATLAB模糊C均值聚类FCM改进的推荐系统协同过滤算法分析MovieLens电影数据集
MATLAB模糊C均值聚类FCM改进的推荐系统协同过滤算法分析MovieLens电影数据集
|
12天前
|
算法 数据可视化 数据挖掘
数据分享|R语言改进的K-MEANS(K-均值)聚类算法分析股票盈利能力和可视化
数据分享|R语言改进的K-MEANS(K-均值)聚类算法分析股票盈利能力和可视化
|
12天前
|
数据采集 存储 算法
数据分享|Weka数据挖掘Apriori关联规则算法分析用户网购数据
数据分享|Weka数据挖掘Apriori关联规则算法分析用户网购数据
|
14天前
|
搜索推荐 算法 Java
sort-06-shell sort 希尔排序算法详解
这是一个关于排序算法的系列文章摘要。文章汇总了各种排序算法,包括冒泡排序、快速排序、选择排序、堆排序、插入排序、希尔排序、归并排序、计数排序、桶排序以及大文件外部排序。特别地,希尔排序是一种改进的插入排序,通过使用不同的步长对元素进行分组排序,以提高效率。算法最终以较小的步长进行排序,接近线性时间复杂度。文章还提供了Java代码实现,并举例说明了希尔排序的过程。所有内容可在开源项目[https://github.com/houbb/sort](https://github.com/houbb/sort)中找到。
|
14天前
|
搜索推荐 算法 Java
sort-05-insert sort 插入排序算法详解
这是一个关于排序算法的系列文章总结,包括冒泡排序、快速排序、选择排序、堆排序、插入排序等10种排序算法的详细讲解和Java实现。插入排序是一种简单直观的排序算法,通过构建有序序列并逐个插入新元素来排序。提供的Java代码展示了插入排序的实现过程,并附有测试示例。所有算法已开源在GitHub项目[https://github.com/houbb/sort](https://github.com/houbb/sort)中。
|
23小时前
|
算法 数据安全/隐私保护 计算机视觉
基于二维CS-SCHT变换和LABS方法的水印嵌入和提取算法matlab仿真
该内容包括一个算法的运行展示和详细步骤,使用了MATLAB2022a。算法涉及水印嵌入和提取,利用LAB色彩空间可能用于隐藏水印。水印通过二维CS-SCHT变换、低频系数处理和特定解码策略来提取。代码段展示了水印置乱、图像处理(如噪声、旋转、剪切等攻击)以及水印的逆置乱和提取过程。最后,计算并保存了比特率,用于评估水印的稳健性。
|
1天前
|
存储 算法 数据可视化
基于harris角点和RANSAC算法的图像拼接matlab仿真
本文介绍了使用MATLAB2022a进行图像拼接的流程,涉及Harris角点检测和RANSAC算法。Harris角点检测寻找图像中局部曲率变化显著的点,RANSAC则用于排除噪声和异常点,找到最佳匹配。核心程序包括自定义的Harris角点计算函数,RANSAC参数设置,以及匹配点的可视化和仿射变换矩阵计算,最终生成全景图像。
|
1天前
|
算法 Serverless
m基于遗传优化的LDPC码NMS译码算法最优归一化参数计算和误码率matlab仿真
MATLAB 2022a仿真实现了遗传优化的归一化最小和(NMS)译码算法,应用于低密度奇偶校验(LDPC)码。结果显示了遗传优化的迭代过程和误码率对比。遗传算法通过选择、交叉和变异操作寻找最佳归一化因子,以提升NMS译码性能。核心程序包括迭代优化、目标函数计算及性能绘图。最终,展示了SNR与误码率的关系,并保存了关键数据。
11 1