STL学习笔记非变易算法
STL学习笔记--非变易算法
非变易算法
C++ STL 的非变易算法(Non-mutating algorithm)是一组不破坏操作数据的模板函数,用来对序列数据进行逐个处理、元素查找、子序列搜索、统计和匹配。作为算法函数参数的迭代器,一般为 Input Iterator 输入迭代器,具有 "++" 迭代和 "*" 访问操作。通过迭代器的元素遍历,可对迭代器区间所界定的元素进行操作。因此,非变易算法具有极为广泛的适用性,基本上可应用于各种容器。
目录:
逐个容器元素 for_each
查找容器元素 find
条件查找容器元素 find_if
邻近查找容器元素 adjacent_find
范围查找容器元素 find_first_of
统计等于某值的容器元素个数 count
条件统计容器元素个数 count_if
元素不匹配查找 mismatch
元素相等判断 equal
子序列搜索 search
重复元素子序列搜索 search_n
最后一个子序列搜索 find_end
逐个容器元素 for_each
1 /* 下面的示例程序将 list 链表容器的元素,调用 for_each 算法函数,通过 print 函数对象,将各个链表的元素乘以3后打印,并输出元素个数
2 */
3 -------------------------------------------------------- 应用 for_each 算法遍历 list 容器
4 #include <algorithm> // 这个头文件很重要的哦
5 #include <list>
6 #include <iostream>
7 using namespace std;
8
9 struct print
10 {
11 int count; // 打印的元素计数
12 print(){count= 0 ;}
13 void operator () ( int x)
14 {
15 cout << 3 *x << endl;
16 count++ ;
17 }
18 };
19
20 int main()
21 {
22 // 双向链表初始化
23 list< int > lInt;
24 lInt.push_back( 29 );
25 lInt.push_back( 32 );
26 lInt.push_back( 16 );
27 lInt.push_back( 22 );
28 lInt.push_back( 28 );
29 lInt.push_back( 27 );
30
31 // 打印链表的元素
32 print p = for_each(lInt.begin(), lInt.end(), print());
33 // 打印的元素个数
34 cout << " 元素个数为: " <<p.count << endl;
35
36 return 0 ;
37 }
查找容器元素 find
1 /* 下面示例程序利用 find 算法函数查找 list 链表中第一个值为 14 的元素
2 */
3 -------------------------------------------------------- 应用 find 算法查找 list 容器的元素
4 #include <algorithm>
5 #include <list>
6 #include <iostream>
7 using namespace std;
8 int main()
9 {
10 // 双向链表初始化
11 list< int > lInt;
12 lInt.push_back( 100 );
13 lInt.push_back( 10 );
14 lInt.push_back( 14 );
15 lInt.push_back( 13 );
16 lInt.push_back( 14 );
17 lInt.push_back( 40 );
18
19 // 查找元素 14
20 list< int >::iterator iLocation = find(lInt.begin(), lInt.end(), 14 );
21 if (iLocation != lInt.end())
22 cout << " 找到元素14 " << endl;
23
24 // 打印第一个14元素前面的那个元素。即打印元素 10
25 cout << " 前一个元素为: " << *(--iLocation) << endl;
26
27 return 0 ;
28 }
条件查找容器元素 find_if
1 /* 下面示例程序使用 find_if 算法在 vector 向量容器上查找首个可被5整除的元素,程序输出为“找到第一个能被5整除的元素15,元素的索引位置为2”
2 */
3 -------------------------------------------------------- 应用 find_if 算法条件查找 vector 容器的元素
4 #include <algorithm>
5 #include <vector>
6 #include <iostream>
7 using namespace std;
8
9 // 谓词判断函数 divby5
10 bool divby5( int x)
11 {
12 return x% 5 ? 0 : 1 ;
13 }
14
15 int main()
16 {
17 vector< int > vInt( 20 ); // 可以参考之前对 vector 的介绍
18 for (unsigned int i= 0 ; i<vInt.size(); i++ )
19 vInt[i] = (i+ 1 )*(i+ 3 );
20
21 vector< int > ::iterator iLocation;
22 iLocation = find_if(vInt.begin(), vInt.end(), divby5);
23
24 if (iLocation != vInt.end())
25 cout << " 找到第一个能被5整除的元素: "
26 << *iLocation << endl // 打印15
27 << " 元素的索引位置为: "
28 << iLocation-vInt.begin() << endl; // 打印2
29
30 return 0 ;
31 }
邻近查找容器元素 adjacent_find
1 /* 调用 adjacent_find 算法函数找出邻近相等的元素11(链表中,有2个11是临近的),再利用是否为奇偶相同,做谓词判断,找出首先同为奇数的 9和11.
2 */
3 -------------------------------------------------------- 应用 adjacent_find 算法临近查找容器的元素
4 #include <algorithm>
5 #include <list>
6 #include <iostream>
7 using namespace std;
8
9 bool parity_equal ( int x, int y)
10 {
11 return (x-y)% 2 == 0 ? 1 : 0 ;
12 }
13
14 int main()
15 {
16 // 初始化链表
17 list< int > lInt;
18 lInt.push_back( 3 );
19 lInt.push_back( 6 );
20 lInt.push_back( 9 );
21 lInt.push_back( 11 );
22 lInt.push_back( 11 );
23 lInt.push_back( 18 );
24 lInt.push_back( 20 );
25 lInt.push_back( 20 );
26 // 查找邻接相等的元素
27 list< int >::iterator iResult = adjacent_find(lInt.begin(), lInt.end());
28 if (iResult != lInt.end())
29 {
30 cout << " 发现链表有两个邻接的元素相等 " << endl;
31 cout << *iResult << endl; // 打印第1 个11
32 ++ iResult;
33 cout << *iResult << endl; // 打印第2 个11
34 }
35
36 // 查找奇偶性相同的邻接元素
37 iResult = adjacent_find(lInt.begin(), lInt.end(), parity_equal);
38 if (iResult != lInt.end())
39 {
40 cout << " 发现有两个邻接元素的奇偶性相同 " << endl;
41 cout << *iResult << endl; // 打印 9
42 ++ iResult;
43 cout << *iResult << endl; // 打印 11
44 }
45
46 return 0 ;
47 }
范围查找容器元素 find_first_of
1 /* 下面示例程序在字符串 "abcdef7ghijklmn" 中查找首个出现在字符串 "zyx3pr7ys" 的字符,结果当然是字符 7
2 */
3 -------------------------------------------------------- 应用 find_first_of 算法范围查找容器元素
4 #include <algorithm>
5 #include <iostream>
6 using namespace std;
7 int main()
8 {
9 // 定义2个字符串
10 char * str1 = " abcdef7ghijklmn " ;
11 char * str2 = " zyx3pr7ys " ;
12 // 范围查找 str1 于 str2 中
13 char * result = find_first_of(str1, str1 + strlen(str1),
14 str2, str2 + strlen(str2));
15 cout << " 字符串 str1 的第一个出现在 str2 的字符为: "
16 << *result << endl; // 打印 7
17
18 return 0 ;
19 }
统计等于某值的容器元素个数 count
1 /* 下面的示例程序链入100个20的余数到双向链表 list 中,然后统计其中等于 9 的元素个数。
2 */
3
4 -------------------------------------------------------- 应用 count 算法统计等于某值的容器元素个数
5 #include <algorithm>
6 #include <list>
7 #include <iostream>
8 using namespace std;
9 int main()
10 {
11 // 链表初始化
12 list< int > lInt;
13 for ( int i= 0 ; i< 100 ; i++ )
14 lInt.push_back(i% 20 );
15 // 统计链表中等于 value 值的元素个数
16 int num = 0 ;
17 int value = 9 ;
18 num = count(lInt.begin(), lInt.end(), value);
19 cout << " 链表中元素等于 value 的元素个数为: "
20 << num << endl; // 打印5
21
22 return 0 ;
23 }
条件统计容器元素个数 count_if
1 /* 下面示例程序,将学生记录放入使用红黑树的 map 容器,然后利用一元谓词判断 setRange20_30 ,统计年龄在20至30岁之间的学生人数
2 */
3
4 -------------------------------------------------------- 应用 count_if 算法统计满足条件的记录数
5 #pragma warning(disable:4786)
6 #include <algorithm>
7 #include <map>
8 #include <iostream>
9 using namespace std;
10
11 // 学生记录结构体
12 struct StudentRecord
13 {
14 struct StudentInfo
15 {
16 char * name;
17 int year;
18 char * addr;
19 };
20 int id; // 学号
21 StudentInfo sf; // 学生信息
22 StudentRecord( int id_, char * name_, int year_, char * addr_)
23 {
24 id = id_;
25 sf.name = name_;
26 sf.year = year_;
27 sf.addr = addr_;
28 }
29 };
30
31 bool setRange20_30(pair< int , StudentRecord::StudentInfo> s)
32 {
33 // 20 < x < 30
34 if (s.second.year > 20 && s.second.year < 30 )
35 return 1 ;
36
37 return 0 ;
38 }
39
40 int main()
41 {
42 // 学生数据
43 StudentRecord st1 = StudentRecord( 1 , " 李强 " , 21 , " 北京 " );
44 StudentRecord st2 = StudentRecord( 2 , " 李文 " , 29 , " 山东 " );
45 StudentRecord st3 = StudentRecord( 3 , " 张三 " , 12 , " 江苏 " );
46 StudentRecord st4 = StudentRecord( 4 , " 李四 " , 23 , " 武汉 " );
47 StudentRecord st5 = StudentRecord( 5 , " 王五 " , 32 , " 上海 " );
48
49 // 映照容器
50 map< int , StudentRecord::StudentInfo> m;
51 // 插入 5条学生记录
52 pair< int , StudentRecord::StudentInfo> pairSt1(st1.id, st1.sf);
53 m.insert(pairSt1);
54 pair< int , StudentRecord::StudentInfo> pairSt2(st2.id, st2.sf);
55 m.insert(pairSt2);
56 pair< int , StudentRecord::StudentInfo> pairSt3(st3.id, st3.sf);
57 m.insert(pairSt3);
58 pair< int , StudentRecord::StudentInfo> pairSt4(st4.id, st4.sf);
59 m.insert(pairSt4);
60 pair< int , StudentRecord::StudentInfo> pairSt5(st5.id, st5.sf);
61 m.insert(pairSt5);
62
63 // 条件统计
64 int num = 0 ;
65 num = count_if(m.begin(), m.end(), setRange20_30);
66 cout << " 年龄介于20至30之间的学生人数为: "
67 << num << endl; // 打印 3
68
69 return 0 ;
70 }
元素不匹配查找 mismatch
1 /* 下面示例程序,分别使用了 mismatch 算法函数的两种形式。
2 */
3
4 -------------------------------------------------------- 应用 msimatch 算法比较两个序列的元素
5 #include <algorithm>
6 #include <vector>
7 #include <iostream>
8 using namespace std;
9
10 bool strEqual( const char * s1, const char * s2)
11 {
12 return strcmp(s1, s2) == 0 ? 1 : 0 ;
13 }
14
15 int main()
16 {
17 vector< int > v1, v2;
18 v1.push_back( 2 );
19 v1.push_back( 0 );
20 v1.push_back( 0 );
21 v1.push_back( 6 );
22
23 v2.push_back( 2 );
24 v2.push_back( 0 );
25 v2.push_back( 0 );
26 v2.push_back( 7 );
27
28 // v1 和 v2 不匹配检查
29 pair<vector< int >::iterator, vector< int >::iterator> result = mismatch(v1.begin(), v1.end(), v2.begin());
30
31 if (result.first == v1.end() && result.second == v1.end())
32 cout << " v1 和 v2 完全相同 " << endl;
33 else
34 cout << " v1 和 v2 不相同,不匹配的数是:\n "
35 << *result.first << endl
36 << *result.second << endl << endl;
37
38
39 // 初始化字符串 s1、s2
40 char * s1[]={ " apple " , " pear " , " watermelon " , " banana " , " grape " };
41 char * s2[]={ " apple " , " pears " , " watermelons " , " banana " , " grape " };
42 // s1 和 s2 不匹配检查
43 pair< char **, char **> result2 = mismatch(s1, s1+ 5 , s2, strEqual);
44 if (result2.first == s1+ 5 && result2.second == s2+ 5 )
45 cout << " s1和s2完全相同 " << endl;
46 else
47 cout << " s1 与 s2不相同,不匹配的字符串为:\n "
48 << s1[result2.first - s1] << endl
49 << s2[result2.second - s2] << endl << endl;
50
51 return 0 ;
52 }
元素相等判断 equal
1 /* 下面示例程序,利用二元谓词判断 absEqual ,判断出两个 vector 向量容器的元素均绝对值相等。
2 */
3
4 -------------------------------------------------------- 应用 equal 算法判断容器元素是否绝对值相等
5 #include <algorithm>
6 #include <vector>
7 #include <iostream>
8 using namespace std;
9
10 bool absEqual( int a, int b)
11 {
12 return (a==abs(b) || abs(a)==b) ? 1 : 0 ;
13 }
14
15 int main()
16 {
17 vector< int > v1( 5 );
18 vector< int > v2( 5 );
19 for (unsigned int i= 0 ; i<v1.size(); i++ )
20 {
21 v1[i] = i;
22 v2[i] = - 1 * i;
23 }
24
25 // v1、v2 相等检查
26 if (equal(v1.begin(), v1.end(), v2.begin(), absEqual))
27 cout << " v1 和 v2 元素的绝对值完全相等 " << endl;
28 else
29 cout << " v1 和 v2 元素的绝对值不完全相等 " << endl;
30
31 return 0 ;
32 }
子序列搜索 search
1 /* 下面示例程序,搜索 vector 向量 V1={5, 6, 7, 8, 9}是否包含子序列向量容器 v2={7, 8}.
2 */
3
4 -------------------------------------------------------- 应用 search 方法搜索子序列
5 #include <algorithm>
6 #include <vector>
7 #include <iostream>
8 using namespace std;
9 int main()
10 {
11 // 初始化向量 v1
12 vector< int > v1;
13 v1.push_back( 5 );
14 v1.push_back( 6 );
15 v1.push_back( 7 );
16 v1.push_back( 8 );
17 v1.push_back( 9 );
18 // 初始化向量 v2
19 vector< int > v2;
20 v2.push_back( 7 );
21 v2.push_back( 8 );
22 // 检查 v2 是否构成 v1 的子序列
23 vector< int > ::iterator iterLocation;
24 iterLocation = search(v1.begin(), v1.end(), v2.begin(), v2.end());
25 // 打印从 v1[2]开始匹配
26 if (iterLocation != v1.end())
27 cout << " v2 的元素包含在 v1 中,起始元素为: "
28 << " v1[ " << iterLocation - v1.begin() << " ] \n " ;
29 else
30 cout << " v2的元素不包含在v1中. " << endl;
31
32 return 0 ;
33 }
重复元素子序列搜索 search_n
1 /* 下面示例程序,搜索出向量 v={1, 8, 8, 8, 6, 6, 8}中有3个连续元素8、没有4个连续的元素8,以及有2个连续元素6
2 */
3
4 -------------------------------------------------------- 应用 search_n 算法搜索重复元素值
5 #include <algorithm>
6 #include <vector>
7 #include <iostream>
8 using namespace std;
9 int main()
10 {
11 // 初始化向量 v
12 vector< int > v;
13 v.push_back( 1 );
14 v.push_back( 8 );
15 v.push_back( 8 );
16 v.push_back( 8 );
17 v.push_back( 6 );
18 v.push_back( 6 );
19 v.push_back( 8 );
20
21 // 查找子序列 {8, 8, 8}
22 vector< int > ::iterator iLocation;
23 iLocation = search_n(v.begin(), v.end(), 3 , 8 );
24 if (iLocation != v.end())
25 cout << " 在v中找到3个连续的元素8 " << endl;
26 else
27 cout << " v中没有3个连续的元素8 " << endl;
28
29 // 查找子序列 {8, 8, 8, 8}
30 iLocation = search_n(v.begin(), v.end(), 4 , 8 );
31 if (iLocation != v.end())
32 cout << " 在v中找到4个连续的元素8 " << endl;
33 else
34 cout << " v中没有4个连续的元素8 " << endl;
35
36 // 查找子序列{6, 6}
37 iLocation = search_n(v.begin(), v.end(), 2 , 6 );
38 if (iLocation != v.end())
39 cout << " 在v中找到2个连续的元素6 " << endl;
40 else
41 cout << " v中没有2个连续的元素6 " << endl;
42
43 return 0 ;
44 }
最后一个子序列搜索 find_end
1 /* 下面示例程序,搜索向量 v1={-5, 1, 2, -6, -8, 1, 2, -11}中最后一个与V2={1, 2}匹配的子序列,打印输出为 "v1中找到最后一个匹配v2的子序列,位置在 v1[5]"
2 */
3 -------------------------------------------------------- 应用 find_end 算法搜索最后一个匹配子序列
4 #include <algorithm>
5 #include <vector>
6 #include <iostream>
7 using namespace std;
8 int main()
9 {
10 // 初始化向量 v1
11 vector< int > v1;
12 v1.push_back(- 5 );
13 v1.push_back( 1 );
14 v1.push_back( 2 );
15 v1.push_back(- 6 );
16 v1.push_back(- 8 );
17 v1.push_back( 1 );
18 v1.push_back( 2 );
19 v1.push_back(- 11 );
20
21 // 初始化向量 v2
22 vector< int > v2;
23 v2.push_back( 1 );
24 v2.push_back( 2 );
25
26 // v1中查找最后一个子序列 v2
27 vector< int > ::iterator iLocation;
28 iLocation = find_end(v1.begin(), v1.end(), v2.begin(), v2.end());
29
30 // 打印子序列在 v1 的起始位置 v[5]
31 if (iLocation != v1.end())
32 cout << " v1中找到最后一个匹配 v2 的子序列,位置在 "
33 << " v1[ " << iLocation - v1.begin() << " ] \n " ;
34
35
36 return 0 ;
37 }
------------ 非变易算法小结
C++ STL 算法库中的非变易算法,是一些原则上不会变更操作数据的算法,包括可逐元素循环提交处理的 for_each 算法、用于元素查找的 find/find_if/adjacent_find/find_first_of 算法、用于统计元素个数的 count/count_if 算法、两序列匹配比较 mismatch/equal 算法和子序列搜索 search/search_n/find_end 算法。
作者: Music__Liang
出处: http://HdhCmsTestcnblogs测试数据/music-liang/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利.
分类: STL学习笔记
标签: STL , C++ , 算法
作者: Leo_wl
出处: http://HdhCmsTestcnblogs测试数据/Leo_wl/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
版权信息