STL Non-mutating Algorithms小结

2024-05-27 06:38

本文主要是介绍STL Non-mutating Algorithms小结,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

C++ STL中有许多非变易算法,这些算法不破坏操作数据,用来对序列数据进行逐个处理(for_each)、元素查找(find)、子序列搜索(find_first_of)、统计和匹配(countmismatch)等。非变易算法在实现各种大型复杂一点的算法的时候比较方便,而且比较稳定,这也是STL本身固有的特点。主要列出以下几种,参考了叶志军的那本《C++ STL开发技术导引》,同时也结合网站Cplusplus.com(http://www.cplusplus.com/),查看其实现的原理,以及在C++98C++11两个版本中的区别和变化,以便于做到全方位地学习,主要以C++11为主。例子大部分是书上的例子,这里摆出来主要是为了后期用了想不起来的时候可以回头看一下,呵呵。

逐个容器元素for_each

for_each函数对迭代器区间的每个元素进行循环操作,执行由单参数函数对象f所定义的操作。函数原型为:

UnaryFunction for_each(InputIteratorfirst,InputIterator last, UnaryFunction f)

C++ Reference

http://www.cplusplus.com/reference/algorithm/for_each/?kw=for_each

上可以看到起实现的源码如下:

// Applies function fn to each of the elements in the range [first,last).
template<class InputIterator, class Function>Function for_each(InputIterator first, InputIterator last, Function fn)
{while (first!=last) {fn (*first);++first;}return fn;      // or, since C++11: return move(fn);
}


 

C++98C++11中,该函数的变化不大。

可以清楚地看到并没有修改任何数据,只是执行得函数fn会改动数据。

下面的示例程序将 list 链表容器的元素,调用 for_each 算法函数,通过 print 函数对象,将各个链表的元素乘以3后打印,并输出元素个数。

#include<iostream>
#include<list>
#include<algorithm>
using namespace std;
struct print{int count;print(){count=0;}void operator()(int x){cout<<3*x<<endl;count++;}
};
int main()
{list<int> l;l.push_back(1);l.push_back(2);l.push_back(3);print p=for_each(l.begin(),l.end(),print());cout<<p.count<<endl;return 0;
}


查找容器元素find

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

 

template<class InputIterator, class T>InputIterator find (InputIterator first, InputIterator last, const T& val)
{while (first!=last) {if (*first==val) return first;++first;}return last;
}


 

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

#include<iostream>
#include<algorithm>
#include<list>
using namespace std;
int main()
{list<int> l;l.push_back(1);l.push_back(5);l.push_back(6);l.push_back(19);list<int>::iterator i=find(l.begin(),l.end(),6);if(i!=l.end()){cout<<"找到元素6"<<endl;}cout<<"前一个元素为"<<*(--i)<<endl; return 0;
}


条件查找容器元素find_if

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

函数原型为:

template <class InputIterator, classUnaryPredicate>

  InputIterator find_if (InputIterator first, InputIterator last,UnaryPredicate pred);

实现原理:
// Returns an iterator to the first element in the range [first,last) for which pred returns true. If no such element is found, the function returns last.
template<class InputIterator, class UnaryPredicate>InputIterator find_if (InputIterator first, InputIterator last, UnaryPredicate pred)
{while (first!=last) {if (pred(*first)) return first;++first;}return last;
}


 

下面的实例程序将寻找容器vector中第一个能被5整除的元素。
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
bool divBy5(int x)
{return x%5?0:1;
}
int main()
{vector<int> v(10);for(int j=0;j<v.size();j++)v[j]=(j+1)*(j+3);vector<int>::iterator i;i=find_if(v.begin(),v.end(),divBy5);if(i!=v.end())cout<<"找到第一个能被5整除的元素:"<<*i<<endl<<"索引位置为:"<<i-v.begin()<<endl;return 0;
}


查找临近元素adjacent_find

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

函数原型:

template <class ForwardIterator>ForwardIterator adjacent_find (ForwardIterator first, ForwardIterator last);
template <class ForwardIterator, class BinaryPredicate>ForwardIterator adjacent_find (ForwardIterator first, ForwardIterator last,BinaryPredicate pred);
// Searches the range [first,last) for the first occurrence of two consecutive elements that match, and returns an iterator to the first of these two elements, or last if no such pair is found.
实现原理:
template <class ForwardIterator>ForwardIterator adjacent_find (ForwardIterator first, ForwardIterator last)
{if (first != last){ForwardIterator next=first; ++next;while (next != last) {if (*first == *next)     // or: if (pred(*first,*next)), for version (2)return first;++first; ++next;}}return last;
}


 

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

#include<iostream>
#include<algorithm>
#include<list>
using namespace std;
bool parity_equal(int x,int y){return (x-y)%2==0 ? 1:0;
}
int main()
{list<int> l;l.push_back(3);l.push_back(6);l.push_back(9);l.push_back(11);l.push_back(20);l.push_back(20);list<int>::iterator i=adjacent_find(l.begin(),l.end());if(i!=l.end()){cout<<"发现两个邻接的元素相等:"<<*i<<" ";i++;cout<<*i<<endl;}i=adjacent_find(l.begin(),l.end(),parity_equal);if(i!=l.end()){cout<<"发现两个奇偶性相同的元素:"<<*i<<" ";i++;cout<<*i;}return 0;
}

find_first_of

该函数用于查找某个范围之内的元素。它有两个使用原型,一个是相等,另一个是二元谓词判断。元素找到则返回迭代器,否则返回末位置。该函数在C++98C++11在传入的参数上有稍微的变化,C++98中要求传入的第一个迭代区间必须是前向迭代器ForwardIterator,而C++11没这个要求,下面的函数原型是C++11的函数原型。

template <class InputIterator, class ForwardIterator>InputIterator find_first_of (InputIterator first1, InputIterator last1,ForwardIterator first2, ForwardIterator last2);
template <class InputIterator, class ForwardIterator, class BinaryPredicate>InputIterator find_first_of (InputIterator first1, InputIterator last1,ForwardIterator first2, ForwardIterator last2,BinaryPredicate pred);
//Returns an iterator to the first element in the range [first1,last1) that matches any of the elements in [first2,last2). If no such element is found, the function returns last1.
template<class InputIterator, class ForwardIterator>InputIterator find_first_of ( InputIterator first1, InputIterator last1,ForwardIterator first2, ForwardIterator last2)
{while (first1!=last1) {for (ForwardIterator it=first2; it!=last2; ++it) {if (*it==*first1)          // or: if (pred(*it,*first)) for version (2)return first1;}++first1;}return last1;
}

下面的例子显示字符串1第一个出现在字符串2中的字符。

 

#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
int main()
{char* str1="abceefgh7ijklmn";char* str2="zyx3pr7yst";char* rs=find_first_of(str1,str1+strlen(str1),str2,str2+strlen(str2));cout<<"str1第一个出现在str2的字符为:"<<*rs<<endl;return 0;
}

count

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

template <class InputIterator, class T>typename iterator_traits<InputIterator>::difference_type
count (InputIterator first, InputIterator last, const T& val);
Returns the number of elements in the range [first,last) that compare equal to val.
The function uses operator== to compare the individual elements to val.
template <class InputIterator, class T>typename iterator_traits<InputIterator>::difference_typecount (InputIterator first, InputIterator last, const T& val)
{typename iterator_traits<InputIterator>::difference_type ret = 0;while (first!=last) {if (*first == val) ++ret;++first;}return ret;
}

例子统计数字在数组中出现的次数(Cplusplus.com上的例子)
// count algorithm example
#include <iostream>     // std::cout
#include <algorithm>    // std::count
#include <vector>       // std::vectorint main () {// counting elements in array:int myints[] = {10,20,30,30,20,10,10,20};   // 8 elementsint mycount = std::count (myints, myints+8, 10);std::cout << "10 appears " << mycount << " times.\n";// counting elements in container:std::vector<int> myvector (myints, myints+8);mycount = std::count (myvector.begin(), myvector.end(), 20);std::cout << "20 appears " << mycount  << " times.\n";return 0;
}


count_if

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

 

template <class InputIterator, class UnaryPredicate>typename iterator_traits<InputIterator>::difference_typecount_if (InputIterator first, InputIterator last, UnaryPredicate pred);
Return number of elements in range satisfying condition
Returns the number of elements in the range [first,last) for which pred is true.
template <class InputIterator, class UnaryPredicate>typename iterator_traits<InputIterator>::difference_typecount_if (InputIterator first, InputIterator last, UnaryPredicate pred)
{typename iterator_traits<InputIterator>::difference_type ret = 0;while (first!=last) {if (pred(*first)) ++ret;++first;}return ret;
}
统计奇数出现的次数
#include <iostream>     // std::cout
#include <algorithm>    // std::count_if
#include <vector>       // std::vectorbool IsOdd (int i) { return ((i%2)==1); }int main () {std::vector<int> myvector;for (int i=1; i<10; i++) myvector.push_back(i); // myvector: 1 2 3 4 5 6 7 8 9int mycount = count_if (myvector.begin(), myvector.end(), IsOdd);std::cout << "myvector contains " << mycount  << " odd values.\n";return 0;
}


 

mismatch

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

template <class InputIterator1, class InputIterator2>pair<InputIterator1, InputIterator2>mismatch (InputIterator1 first1, InputIterator1 last1,InputIterator2 first2);
template <class InputIterator1, class InputIterator2, class BinaryPredicate>pair<InputIterator1, InputIterator2>mismatch (InputIterator1 first1, InputIterator1 last1,InputIterator2 first2, BinaryPredicate pred);Compares the elements in the range [first1,last1) with those in the range beginning at first2, and returns the first element of both sequences that does not match.
The elements are compared using operator== (or pred, in version (2)).
The function returns a pair of iterators to the first element in each range that does not match.template <class InputIterator1, class InputIterator2>pair<InputIterator1, InputIterator2>mismatch (InputIterator1 first1, InputIterator1 last1, InputIterator2 first2 )
{while ( (first1!=last1) && (*first1==*first2) )  // or: pred(*first1,*first2), for version 2{ ++first1; ++first2; }return std::make_pair(first1,first2);
}


 

例子是比较两个整型容器,并找出不匹配的数字。

 

#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
int main()
{vector<int> v1,v2;v1.push_back(1);v1.push_back(1);v1.push_back(2);v2.push_back(1);v2.push_back(1);v2.push_back(3);pair<vector<int>::iterator,vector<int>::iterator> rs=mismatch(v1.begin(),v1.end(),v2.begin());if(rs.first==v1.end()&&rs.second==v2.end()){cout<<"v1、v2完全相同";}else{cout<<"v1、v2不同"<<v1[rs.first-v1.begin()]<<" "<<v2[rs.second-v2.begin()]<<endl;}return 0;
}


equal

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

template <class InputIterator1, class InputIterator2>bool equal (InputIterator1 first1, InputIterator1 last1,InputIterator2 first2);
template <class InputIterator1, class InputIterator2, class BinaryPredicate>bool equal (InputIterator1 first1, InputIterator1 last1,InputIterator2 first2, BinaryPredicate pred);Compares the elements in the range [first1,last1) with those in the range beginning at first2, and returns true if all of the elements in both ranges match.
The elements are compared using operator== (or pred, in version (2)).template <class InputIterator1, class InputIterator2>bool equal ( InputIterator1 first1, InputIterator1 last1, InputIterator2 first2 )
{while (first1!=last1) {if (!(*first1 == *first2))   // or: if (!pred(*first1,*first2)), for version 2return false;++first1; ++first2;}return true;
}


 

下面的例子用于比较两容器中数字绝对值是否相等。
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
bool absEqual(int a,int b)
{return abs(a) == abs(b) ? 1 : 0;
}
int main()
{vector<int> v1(5);vector<int> v2(5);for(int i=0;i<v1.size();i++){v1[i]=i;v2[i]=-1*i;}if(equal(v1.begin(), v1.end(), v2.begin(), absEqual)) {cout << "v1 v2绝对值完全相等" << endl;} else {cout << "v1 v2绝对值不完全相等" << endl;}return 0;
}

search

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

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

template <class ForwardIterator1, class ForwardIterator2>ForwardIterator1 search (ForwardIterator1 first1, ForwardIterator1 last1,ForwardIterator2 first2, ForwardIterator2 last2);
template <class ForwardIterator1, class ForwardIterator2, class BinaryPredicate>ForwardIterator1 search (ForwardIterator1 first1, ForwardIterator1 last1,ForwardIterator2 first2, ForwardIterator2 last2,BinaryPredicate pred);Searches the range [first1,last1) for the first occurrence of the sequence defined by [first2,last2), and returns an iterator to its first element, or last1 if no occurrences are found.
The elements in both ranges are compared sequentially using operator== (or pred, in version (2)): A subsequence of [first1,last1) is considered a match only when this is true for all the elements of [first2,last2).
This function returns the first of such occurrences. For an algorithm that returns the last instead, see find_end. 在C++11中,If [first2,last2) is an empty range, the function returns first1.而在C++98中,If [first2,last2) is an empty range, the result is unspecified.template<class ForwardIterator1, class ForwardIterator2>ForwardIterator1 search ( ForwardIterator1 first1, ForwardIterator1 last1,ForwardIterator2 first2, ForwardIterator2 last2)
{if (first2==last2) return first1;  // specified in C++11while (first1!=last1){ForwardIterator1 it1 = first1;ForwardIterator2 it2 = first2;while (*it1==*it2) {    // or: while (pred(*it1,*it2)) for version 2++it1; ++it2;if (it2==last2) return first1;if (it1==last1) return last1;}++first1;}return last1;
}


 

下面的例子指出二者的区别。

 

#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
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;//打印2cout << "Position of find_first_of: " << ivFind - v1.begin() << endl;//打印1return 0;
}

重复元素子序列搜索search_n

template <class ForwardIterator, class Size, class T>ForwardIterator search_n (ForwardIterator first, ForwardIterator last,Size count, const T& val);
template <class ForwardIterator, class Size, class T, class BinaryPredicate>ForwardIterator search_n ( ForwardIterator first, ForwardIterator last,Size count, const T& val, BinaryPredicate pred );Searches the range [first,last) for a sequence of count elements, each comparing equal to val (or for which pred returns true).
The function returns an iterator to the first of such elements, or last if no such sequence is found.template<class ForwardIterator, class Size, class T>ForwardIterator search_n (ForwardIterator first, ForwardIterator last,Size count, const T& val)
{ForwardIterator it, limit;Size i;limit=first; std::advance(limit,std::distance(first,last)-count);while (first!=limit){it = first; i=0;while (*it==val)       // or: while (pred(*it,val)) for the pred version{ ++it; if (++i==count) return first; }++first;}return last;
}
//向量内统计数字出现次数。
#include <algorithm>
#include <vector>
#include <iostream>
int main(){using namespace std;//初始化向量v={1, 8, 8, 8, 6, 6, 8}vector<int> v;v.push_back(1);v.push_back(8);v.push_back(8);v.push_back(8);v.push_back(6);v.push_back(6);v.push_back(8);//查找子序列{8, 8, 8}vector<int>::iterator iLocation;iLocation=search_n(v.begin(), v.end(), 3, 8);if(iLocation != v.end())cout << "在v中找到3个连续的元素8" << endl;else cout << "v中没有3个连续的元素8" << endl;//查找子序列{8, 8, 8, 8}iLocation=search_n(v.begin(), v.end(), 4, 8);if(iLocation != v.end())cout << "在v中找到4个连续的元素8" << endl;else cout << "v中没有4个连续的元素8" << endl;//查找子序列{6, 6}iLocation=search_n(v.begin(), v.end(), 2, 6);if(iLocation != v.end())cout << "在v中找到2个连续的元素6" << endl;else cout << "v中没有2个连续的元素6" << endl;return 0;
}


 

find_end

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

template <class ForwardIterator1, class ForwardIterator2>ForwardIterator1 find_end (ForwardIterator1 first1, ForwardIterator1 last1,ForwardIterator2 first2, ForwardIterator2 last2);
template <class ForwardIterator1, class ForwardIterator2, class BinaryPredicate>ForwardIterator1 find_end (ForwardIterator1 first1, ForwardIterator1 last1,ForwardIterator2 first2, ForwardIterator2 last2,BinaryPredicate pred);Searches the range [first1,last1) for the last occurrence of the sequence defined by [first2,last2), and returns an iterator to its first element, or last1 if no occurrences are found.
The elements in both ranges are compared sequentially using operator== (or pred, in version (2)): A subsequence of [first1,last1) is considered a match only when this is true for all the elements of [first2,last2).template<class ForwardIterator1, class ForwardIterator2>ForwardIterator1 find_end (ForwardIterator1 first1, ForwardIterator1 last1,ForwardIterator2 first2, ForwardIterator2 last2)
{if (first2==last2) return last1;  // specified in C++11ForwardIterator1 ret = last1;while (first1!=last1){ForwardIterator1 it1 = first1;ForwardIterator2 it2 = first2;while (*it1==*it2) {    // or: while (pred(*it1,*it2)) for version (2)++it1; ++it2;if (it2==last2) { ret=first1; break; }if (it1==last1) return ret;}++first1;}return ret;
}
在C++11中,If [first2,last2) is an empty range, the function returns last1.
在C++98中,If [first2,last2) is an empty range, the result is unspecified.
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
int main(void) {vector<int> v, v2;//v={1,3,5,4,3,5,7}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={3,5}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<< iv - v.begin() << endl;//3}return 0;
}


 

 

这篇关于STL Non-mutating Algorithms小结的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1006723

相关文章

分布式系统的个人理解小结

分布式系统:分的微小服务,以小而独立的业务为单位,形成子系统。 然后分布式系统中需要有统一的调用,形成大的聚合服务。 同时,微服务群,需要有交流(通讯,注册中心,同步,异步),有管理(监控,调度)。 对外服务,需要有控制的对外开发,安全网关。

STL经典案例(四)——实验室预约综合管理系统(项目涉及知识点很全面,内容有点多,耐心看完会有收获的!)

项目干货满满,内容有点过多,看起来可能会有点卡。系统提示读完超过俩小时,建议分多篇发布,我觉得分篇就不完整了,失去了这个项目的灵魂 一、需求分析 高校实验室预约管理系统包括三种不同身份:管理员、实验室教师、学生 管理员:给学生和实验室教师创建账号并分发 实验室教师:审核学生的预约申请 学生:申请使用实验室 高校实验室包括:超景深实验室(可容纳10人)、大数据实验室(可容纳20人)、物联网实验

C++ STL 适配器

系列文章目录 模板特例化,偏特化,左右值引用 https://blog.csdn.net/surfaceyan/article/details/126794013 C++ STL 关联容器 https://blog.csdn.net/surfaceyan/article/details/127414434 C++ STL 序列式容器(二) https://blog.csdn.net/surfac

C++ STL关联容器Set与集合论入门

1. 简介 Set(集合)属于关联式容器,也是STL中最实用的容器,关联式容器依据特定的排序准则,自动为其元素排序。Set集合的底层使用一颗红黑树,其属于一种非线性的数据结构,每一次插入数据都会自动进行排序,注意,不是需要排序时再排序,而是每一次插入数据的时候其都会自动进行排序。因此,Set中的元素总是顺序的。 Set的性质有:数据自动进行排序且数据唯一,是一种集合元素,允许进行数学上的集合相

stl的sort和手写快排的运行效率哪个比较高?

STL的sort必然要比你自己写的快排要快,因为你自己手写一个这么复杂的sort,那就太闲了。STL的sort是尽量让复杂度维持在O(N log N)的,因此就有了各种的Hybrid sort algorithm。 题主你提到的先quicksort到一定深度之后就转为heapsort,这种是introsort。 每种STL实现使用的算法各有不同,GNU Standard C++ Lib

Linux环境配置中问题小结

在Linux环境配置中,遇到问题首先猜测: 1、是否是权限问题; 2、软连接是否配置;

STL set整理

#include<set>#include<cstdio>#include<iterator>#include<iostream>#include<algorithm>using namespace std;//set 集合的操作//multisetset<int>Set1;set<int>Set2;set<int>Set3;/*begin() 返回指向第一个元素的迭代器

【C++STL(十四)】一个哈希桶简单模拟实现unordered_map/set

目录 前言 一、改造哈希桶 改造结点类 改造主体  模板参数改造  迭代器(重点) 改造完整哈希桶 unordered_map模拟实现 unordered_set模拟实现 前言 前面的文章都有说unordered_map/set的底层结构就是哈希表,严格来说是哈希桶,那么接下来我们就尝试使用同一个哈希桶来模拟实现一下。整体的逻辑和一棵红黑树封装map/set类似,所以

STL学习之零散记录(不断更新中)

我用到什么就写什么,所以不是太注重排版,等写多了以后再整理: 1:vector<int> V,V.pop_back()弹出最后一个元素 2:优先级队列不能设置迭代器,因为没有 3:   #include <bitset> //位运算 string str2(str,0,8);//将str字符串数组截取0~7号元素,string自带的功能bitset<8>

long long,_int64使用小结

前言:   在16位环境下,int/unsigned int 占16位,long/unsigned long占32位   在32位环境下,int占32位,unsigned int占16位,long/unsigned long占32位 何时需要使用:   long 和 int 范围是[-2^31,2^31),即-2147483648~2147483647,而unsigned范围是[0,2^32),