欢迎访问我的新博客:http://www.milkcu.com/blog/

原文地址:http://www.milkcu.com/blog/archives/1394600460.html

原创:STL非变易算法 - STL算法

作者:MilkCu(http://blog.csdn.net/milkcu

本文地址:http://blog.csdn.net/milkcu/article/details/21114613

摘要:C++ STL标准模板库在数据结构和算法的时间领域发挥着重要作用,极大的提高了开发效率。STL的三大组成部分为容器、迭代器、算法,本文主要讲解STL算法中的非变易算法。本文从实践的角度简单介绍了一下相关函数的使用。

引言

C++ STL的非变易算法(Non-mutating algorithms)是一组不破坏函数数据的模板函数,用来对序列数据进行逐个处理、元素查找、子序列搜索、统计和匹配,基本上可用于各种容器。下面的叙述中迭代器区间默认为[first, last),迭代器具有“++”迭代和“*”访问操作。

逐个处理算法

for_each函数

该函数对迭代器区间的每个元素,执行单参数函数对象定义的操作。

下面的实例程序,将打印容器vector中的每个元素。

#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
void print(int x) {
cout << x << " ";
}
int main(void) {
vector<int> v;
for(int i = 0; i < 10; i++) {
v.push_back(i * 2);
}
for_each(v.begin(), v.end(), print);
return 0;
}

结果输出为:

0 2 4 6 8 10 12 14 16 18

元素查找算法

find函数

该函数用于查找等于某值的元素。如果迭代器i所指的元素满足*i == value,则返回迭代器i。未找到满足条件的元素,返回last。只要找到第一个满足条件的元素就返回迭代器位置,不再继续查找。

下面的示例程序查找容器vector中,第一个值为6的元素,打印元素位置及其前一元素。

#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
int main(void) {
vector<int> v;
for(int i = 0; i < 10; i++) {
v.push_back(i * 2);
}
vector<int>::iterator iv = find(v.begin(), v.end(), 6);
if(iv == v.end()) {
cout << "Find nothing." << endl;
} else {
cout << "The postion of " << *iv << " is " << iv - v.begin() << endl;
cout << "The previous element of it is " << *(--iv) << endl;
}
return 0;
}

结果输出为:

The postion of 6 is 3

The previous element of it is 4

find_if函数

该函数是find的一个谓词判断版本,查找满足谓词判断函数的元素。

下面的实例程序将寻找容器vector中第一个能被3整除的元素。

#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
int divBy3(int x) {
return x % 3 ? 0 : 1;
}
int main(void) {
vector<int> v;
for(int i = 1; i < 10; i++) {
v.push_back(i * 2);
}
vector<int>::iterator iv = find_if(v.begin(), v.end(), divBy3);
if(iv == v.end()) {
cout << "None could be divided by 3 with no remaineder." << endl;
} else {
cout << *iv << " could be divided by 3 with no remainder." << endl;
}
return 0;
}

结果输出为:

6 could be divided by 3 with no remainder.

adjacent_find函数

该函数用于查找相等或满足条件的邻近元素对。它有两个使用原型,一个用于查找相等的两个连续元素,另一个使用二元谓词判断,查找满足条件的邻近元素对。

下面的实例程序用于寻找容器中相等的元素和奇偶性相同的元素。

#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
int parity_equal(int x, int y) {
return (x - y) % 2 == 0 ? 1 : 0;
}
int main(void) {
vector<int> v;
v.push_back(1);
v.push_back(2);
v.push_back(3);
v.push_back(5);
v.push_back(5);
v.push_back(7);
vector<int>::iterator iv = adjacent_find(v.begin(), v.end());
if(iv != v.end()) {
cout << "There are two equal elements." << endl;
cout << "It is " << *iv << endl;
}
iv = adjacent_find(v.begin(), v.end(), parity_equal);
if(iv != v.end()) {
cout << "There are two parity euqal elements." << endl;
cout << "They are " << *iv << " and ";
iv++;
cout << *iv << endl;
}
return 0;
}

输出结果为:

There are two equal elements.

It is 5

There are two parity euqal elements.

They are 3 and 5

find_first_of函数

该函数用于查找某个范围之内的元素。它有两个使用原型,一个是相等,另一个是二元谓词判断。元素找到则返回迭代器,否则返回末位置。

下面的实例程序用于计算容器v2中元素在容器v中重合出现的首位置。

#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
int main(void) {
vector<int> v;
v.push_back(1);
v.push_back(2);
v.push_back(2);
v.push_back(3);
v.push_back(5);
v.push_back(5);
v.push_back(7);
vector<int> v2;
v2.push_back(3);
v2.push_back(3);
v2.push_back(5);
vector<int>::iterator iv = find_first_of(v.begin(), v.end(), v2.begin(), v2.end());
cout << "The position of the first equal element is " << iv - v.begin() << endl;
return 0;
}

输出结果为:

The position of the first equal element is 3

元素统计算法

count函数

该函数用于计算容器中某个给定值的出现次数。它有两个使用原型,区别在于计数是直接返回还是引用返回。

下面的实例程序计算了容器中5的出现次数,结果直接返回。

#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
int main(void) {
vector<int> v;
for(int i = 0; i < 17; i++) {
v.push_back(i % 6);
}
int num = count(v.begin(), v.end(), 5);
cout << "The number of 5 is " << num << endl;
return 0;
}

输出结果为:

The number of 5 is 2

count_if函数

该函数使用谓词判断函数,统计迭代器区间上满足条件的元素个数。它有两个使用原型,区别在与计数是直接返回还是引用返回。

下面的实例程序统计了容器中大于10的数字的出现次数,结果直接返回。

#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
int greaterThan10(int x) {
return x > 10 ? 1 : 0;
}
int main(void) {
vector<int> v;
for(int i = 0; i < 17; i++) {
v.push_back(i);
}
int num = count_if(v.begin(), v.end(), greaterThan10);
cout << "The number of the figure that greater than 10 is " << num << endl;
return 0;
}

输出结果为:

The number of the figure that greater than 10 is 6

序列匹配算法

mismatch函数

该函数用于比较两个序列,找出首个不匹配元素的位置。它有两个使用原型,分别为不相等和不满足二元谓词条件。

该函数还涉及到pair的使用。

下面的实例程序比较两个整型容器,并找出不匹配的数字。

#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
int main(void) {
vector<int> v1, v2;
v1.push_back(3);
v1.push_back(5);
v1.push_back(5);
v2.push_back(3);
v2.push_back(5);
v2.push_back(7);
pair<vector<int>::iterator, vector<int>::iterator> result = mismatch(v1.begin(), v1.end(), v2.begin());
if(result.first == v1.end() && result.second == v2.end()) {
cout << "v1 is same as v2." << endl;
} else {
cout << "The dismatching figure are "
<< *(result.first) << " and "
<< *(result.second) << endl;
}
return 0;
}

输出结果为:

The dismatching figure are 5 and 7

equal函数

该函数逐一比较两个序列的元素是否相等,返回值为true/false,不返回迭代器值。它有两个使用原型,分别为元素相等和二元谓词判断条件。

下面的实例程序用于比较两容器中数字绝对值是否相等。

#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
int absEqual(int x, int y) {
//return (x == abs(y) || y == abs(x)) ? 1 : 0;
return abs(x) == abs(y) ? 1 : 0;
}
int main(void) {
vector<int> v1, v2;
v1.push_back(3);
v1.push_back(5);
v1.push_back(5);
v2.push_back(3);
v2.push_back(5);
v2.push_back(-5);
if(equal(v1.begin(), v1.end(), v2.begin(), absEqual)) {
cout << "The elements of v1 and v2 are equal in abosolute value." << endl;
} else {
cout << "The elements of v1 and v2 are not equal in abosolute value." << endl;
}
return 0;
}

输出结果为:

The elements of v1 and v2 are equal in abosolute value.

子序列搜索算法

search函数

该函数在一个序列中搜索与另一序列匹配的子序列。它有两个使用原型,分别为完全匹配和二元谓词判断。匹配成功则返回子序列的首个元素的迭代器值。

search函数与find_first_of函数形似,但不相同。search找的是一块相同的区域,要求这块区域与后面列表的元素及其顺序相同;find_first_of找的是一个元素,只要这个元素是后面一个列表的任意一个就行。

下面的实例程序说明了search与find_first_of的不同。

#include <iostream>
#include <algorithm>
#include <vector>
int main(void) {
vector<int> v1, v2;
v1.push_back(1);
v1.push_back(4);
v1.push_back(2);
v1.push_back(3);
v1.push_back(4);
v2.push_back(2);
v2.push_back(3);
v2.push_back(4);
vector<int>::iterator ivSearch, ivFind;
ivSearch = search(v1.begin(), v1.end(), v2.begin(), v2.end());
ivFind = find_first_of(v1.begin(), v1.end(), v2.begin(), v2.end());
cout << "Position of search: " << ivSearch - v1.begin() << endl;
cout << "Position of find_first_of: " << ivFind - v1.begin() << endl;
return 0;
}

输出结果为:

Position of search: 2

Position of find_first_of: 1

search_n函数

该函数用于搜索序列中是否有一系列元素值均为某个给定值的子序列。它有两个使用原型,分别为值相等和满足谓词判断条件。

下面的实例程序展示了寻找3个连续的数字8的过程。

#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
int main(void) {
vector<int> v;
v.push_back(3);
v.push_back(8);
v.push_back(8);
v.push_back(8);
v.push_back(4);
vector<int>::iterator iv = search_n(v.begin(), v.end(), 3, 8);
if(iv == v.end()) {
cout << "There are no three consecutive 8." << endl;
} else {
cout << "Three consecutive 8 is founded." << endl;
}
return 0;
}

结果输出为:

Three consecutive 8 is founded.

find_end函数

该函数用于在一个序列中搜索出最后一个与另一序列匹配的子序列。用search函数作用相似,方向相反。

下面的实例程序,展示了搜索容器v中最后一个与v1匹配的子序列的过程。

#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
int main(void) {
vector<int> v, v2;
v.push_back(1);
v.push_back(3);
v.push_back(5);
v.push_back(3);
v.push_back(5);
v.push_back(7);
v2.push_back(3);
v2.push_back(5);
vector<int>::iterator iv = find_end(v.begin(), v.end(), v2.begin(), v2.end());
if(iv != v.end()) {
cout << "The position of last matching subsequence is " << iv - v.begin() << endl;
}
return 0;
}

输出结果为:

The position of last matching subsequence is 3

小结

本文主要介绍了C++ STL算法库中的非变易算法,是一些原则上不会变更操作数据的算法,包括:

  • 逐个查找算法:for_each
  • 元素搜索算法:find, find_if, adjacent_find, find_first_of
  • 元素统计算法:count, count_if
  • 序列匹配算法:dismatch, equal
  • 子序列搜索算法:search, search_n, find_end

这些函数均包含于<algorithm>头文件,本文给出的所有代码在VS2010中编译运行通过。

参考

[1] http://www.cplusplus.com/reference/algorithm/, <algorithm> - C++ Reference;

[2] C++ STL开发技术导引, 叶志军, 人民邮电出版社.

(全文完)

STL非变易算法 - STL算法的更多相关文章

  1. stl非变易算法(二)

    这里接着上篇stl非变易算法(一)进行总结.主要解析算法函数count.count_if.mismatch.equal.search.search_n以及find_end.给出算法函数的实现及測试用例 ...

  2. STL非变易算法

    非变易算法:原则上不会变更操作数据的算法. [1]    for_each:逐个容器元素,原型for_each(InputIter first, InputIter last, Function f) ...

  3. 变易算法 - STL算法

    欢迎访问我的新博客:http://www.milkcu.com/blog/ 原文地址:http://www.milkcu.com/blog/archives/mutating-algorithms.h ...

  4. 【STL学习】堆相关算法详解与C++编程实现(Heap)

    转自:https://blog.csdn.net/xiajun07061225/article/details/8553808 堆简介   堆并不是STL的组件,但是经常充当着底层实现结构.比如优先级 ...

  5. STL 笔记(五) 算法 algorithm

    在 STL 中,算法是一系列的函数模版.STL 提供了大概 70 个算法,由头文件 <algorithm>.<numeric>.<functional>组成. 头文 ...

  6. 论C++STL源代码中关于堆算法的那些事

    关于堆,我们肯定熟知的就是它排序的时间复杂度在几个排序算法里面算是比較靠上的O(nlogn)常常会拿来和高速排序和归并排序讨论,并且它还有个长处是它的空间复杂度为O(1), 可是STL中没有给我们提供 ...

  7. STL学习笔记(排序算法)

    STL提供了好几种算法对区间内的元素排序.出来完全排序外,还支持局部排序. 对所有元素排序 void sort(RandomAccessIterator beg,RandomAccessIterato ...

  8. STL源码剖析:算法

    启 算法,问题之解法也 算法好坏的衡量标准:时间和空间,单位是对数.一次.二次.三次等 算法中处理的数据,输入方式都是左闭又开,类型就迭代器, 如:[first, last) STL中提供了很多算法, ...

  9. 泛型编程、STL的概念、STL模板思想及其六大组件的关系,以及泛型编程(GP)、STL、面向对象编程(OOP)、C++之间的关系

    2013-08-11 10:46:39 介绍STL模板的书,有两本比较经典: 一本是<Generic Programming and the STL>,中文翻译为<泛型编程与STL& ...

随机推荐

  1. JavaEE(4) - JMS实现企业PTP消息处理

    1. 在Weblogic服务器上配置PTP消息目的 配置持久化: Services-->Persistence Stores-->New(Create FileStore, Create ...

  2. 讨厌OpenSSL

    在OpenSSL心脏出血后,.我相信很多人都出了血.而流下眼泪...瞬间出现在网上了很多吐槽OpenSSL文章还是那条,窝火一刻仿佛心脏被释放出来,按照这个忙疯了,我吐在嘈杂.在这些年被雪OpenSS ...

  3. NYOJ 330 一个简单的数学

    一个简单的数学题 时间限制:3000 ms  |  内存限制:65535 KB 难度:3 描写叙述 zyc近期迷上了数学,一天,dj想出了一道数学题来难住他.算出1/n,但zyc一时答不上来希望大家能 ...

  4. C#关于HttpClient的统一配置(一)

    public class BaseHttpClient { protected string contentType; public BaseHttpClient() { this.contentTy ...

  5. Flex 日志管理

    在Flex中调试方法有两种: 一是用trace()函数,在flex builder中进行调试: 二是用logTarget类,例如以下代码: // Create a target. var logTar ...

  6. 我们的空间是它圆——基于Poicare对宇宙的模型

    一般 状态 在人类文明的开始,并探讨了空间和时间的混乱从来没有停止过.马跑得更快.鱼下潜深.鸟振翅高飞,但是,人类并没有很深的不满潜飞不高.为什么?其原因是,马跑得更快,但它不会不知道他们为什么会跑得 ...

  7. $.each()方法详解

    $.each()方法详解 each()函数具有十分强大的遍历功能,可以遍历一维数组.多维数组.Dom.Json等. 在JavaScript中使用$.each可以大大减轻我们的工作量. 1.处理一维数组 ...

  8. centos 7安装mysql5.5

    首先centos7 已经不支持mysql,因为收费了你懂得,所以内部集成了mariadb,而安装mysql的话会和mariadb的文件冲突,所以需要先卸载掉mariadb,以下为卸载mariadb,安 ...

  9. 利用@media screen实现网页布局的自适应,@media screen and

    开始研究响应式web设计,CSS3 Media Queries是入门.Media Queries,其作用就是允许添加表达式用以确定媒体的环境情况,以此来应用不同的样式表.换句话说,其允许我们在不改变内 ...

  10. C语言对mysql数据库的操作

    原文:C语言对mysql数据库的操作 这已经是一相当老的话题.不过今天我才首次使用,把今天的一些体会写下来,也许能给一些新手带来一定的帮助,更重要的是供自己今后忘记的怎么使用而进行查阅的! 我们言归正 ...