【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. }
目录
打赏
0
0
0
0
13
分享
相关文章
婚恋交友系统平台 相亲交友平台系统 婚恋交友系统APP 婚恋系统源码 婚恋交友平台开发流程 婚恋交友系统架构设计 婚恋交友系统前端/后端开发 婚恋交友系统匹配推荐算法优化
婚恋交友系统平台通过线上互动帮助单身男女找到合适伴侣,提供用户注册、个人资料填写、匹配推荐、实时聊天、社区互动等功能。开发流程包括需求分析、技术选型、系统架构设计、功能实现、测试优化和上线运维。匹配推荐算法优化是核心,通过用户行为数据分析和机器学习提高匹配准确性。
187 3
【排序算法】八大排序(下)(c语言实现)(附源码)
本文继续学习并实现了八大排序算法中的后四种:堆排序、快速排序、归并排序和计数排序。详细介绍了每种排序算法的原理、步骤和代码实现,并通过测试数据展示了它们的性能表现。堆排序利用堆的特性进行排序,快速排序通过递归和多种划分方法实现高效排序,归并排序通过分治法将问题分解后再合并,计数排序则通过统计每个元素的出现次数实现非比较排序。最后,文章还对比了这些排序算法在处理一百万个整形数据时的运行时间,帮助读者了解不同算法的优劣。
193 7
【排序算法】八大排序(上)(c语言实现)(附源码)
本文介绍了四种常见的排序算法:冒泡排序、选择排序、插入排序和希尔排序。通过具体的代码实现和测试数据,详细解释了每种算法的工作原理和性能特点。冒泡排序通过不断交换相邻元素来排序,选择排序通过选择最小元素进行交换,插入排序通过逐步插入元素到已排序部分,而希尔排序则是插入排序的改进版,通过预排序使数据更接近有序,从而提高效率。文章最后总结了这四种算法的空间和时间复杂度,以及它们的稳定性。
159 8
JVM知识体系学习六:JVM垃圾是什么、GC常用垃圾清除算法、堆内存逻辑分区、栈上分配、对象何时进入老年代、有关老年代新生代的两个问题、常见的垃圾回收器、CMS
这篇文章详细介绍了Java虚拟机(JVM)中的垃圾回收机制,包括垃圾的定义、垃圾回收算法、堆内存的逻辑分区、对象的内存分配和回收过程,以及不同垃圾回收器的工作原理和参数设置。
187 4
JVM知识体系学习六:JVM垃圾是什么、GC常用垃圾清除算法、堆内存逻辑分区、栈上分配、对象何时进入老年代、有关老年代新生代的两个问题、常见的垃圾回收器、CMS
c++ STL划分算法;partition()、partition_copy()、stable_partition()、partition_point()详解
这些算法是C++ STL中处理和组织数据的强大工具,能够高效地实现复杂的数据处理逻辑。理解它们的差异和应用场景,将有助于编写更加高效和清晰的C++代码。
92 0
ArrayList简介及使用全方位手把手教学(带源码),用ArrayList实现洗牌算法,3个人轮流拿牌(带全部源码)
文章全面介绍了Java中ArrayList的使用方法,包括其构造方法、常见操作、遍历方式、扩容机制,并展示了如何使用ArrayList实现洗牌算法的实例。
39 0
现有一个接口DataOperation定义了排序方法sort(int[])和查找方法search(int[],int),已知类QuickSort的quickSort(int[])方法实现了快速排序算法
该博客文章通过UML类图和Java源码示例,展示了如何使用适配器模式将QuickSort类和BinarySearch类的排序和查找功能适配到DataOperation接口中,实现算法的解耦和复用。
71 1
现有一个接口DataOperation定义了排序方法sort(int[])和查找方法search(int[],int),已知类QuickSort的quickSort(int[])方法实现了快速排序算法
基于FPGA的图像双线性插值算法verilog实现,包括tb测试文件和MATLAB辅助验证
本项目展示了256×256图像通过双线性插值放大至512×512的效果,无水印展示。使用Matlab 2022a和Vivado 2019.2开发,提供完整代码及详细中文注释、操作视频。核心程序实现图像缩放,并在Matlab中验证效果。双线性插值算法通过FPGA高效实现图像缩放,确保质量。
基于遗传优化算法的风力机位置布局matlab仿真
本项目基于遗传优化算法(GA)进行风力机位置布局的MATLAB仿真,旨在最大化风场发电效率。使用MATLAB2022A版本运行,核心代码通过迭代选择、交叉、变异等操作优化风力机布局。输出包括优化收敛曲线和最佳布局图。遗传算法模拟生物进化机制,通过初始化、选择、交叉、变异和精英保留等步骤,在复杂约束条件下找到最优布局方案,提升风场整体能源产出效率。
基于包围盒的机械臂防碰撞算法matlab仿真
基于包围盒的机械臂防碰撞算法通过构建包围盒来近似表示机械臂及其环境中各实体的空间占用,检测包围盒是否相交以预判并规避潜在碰撞风险。该算法适用于复杂结构对象,通过细分目标对象并逐级检测,确保操作安全。系统采用MATLAB2022a开发,仿真结果显示其有效性。此技术广泛应用于机器人运动规划与控制领域,确保机器人在复杂环境中的安全作业。

热门文章

最新文章

AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等