C++ STL模板是惠普实验室开发的标准开发模板,STL是C++的一部分,STL可分为容器(containers)、迭代器(iterators)、空间配置器(allocator)、配接器(adapters)、算法(algorithms)、仿函数(functors)六个部分,以下案例是针对算法中的非变易与变易算法的总结知识点。
STL 非变易算法(查找遍历) C++ 非变易算法是一组不破坏操作数据的模板函数,用来对序列数据进行逐个处理,元素查找,统计等,并通过迭代器实现元素的遍历,由于迭代器与算法是分离的,因此非变易算法本身具有极为广泛的通用性,基本上可以应用于各种容器上.
逐个遍历容器元素 for_each: 该函数用于对容器的元素进行循环操作,常用于元素遍历.
#include <iostream> #include <list> #include <algorithm> using namespace std;struct MyPrint { int count; MyPrint (){ count = 0 ; } void operator () (int x) { cout << x << endl; count++; } }; int main (int argc, char * argv[]) { list<int > ls {1 ,2 ,3 ,4 ,5 ,6 ,7 ,8 ,9 }; MyPrint p = for_each(ls.begin (), ls.end (), MyPrint ()); cout << "Link Count: " << p.count << endl; system ("pause" ); return 0 ; }
普通查找容器元素 find: 该算法用于查找某个值等于某值得元素,它在迭代区间是(frist,last)
之间寻找value值.
#include <iostream> #include <list> #include <algorithm> using namespace std;int main (int argc, char * argv[]) { list<int > ls{ 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 }; list<int >::iterator it = find (ls.begin (), ls.end (),6 ); if (it != ls.end ()) { cout << "找到了元素" << endl; cout << "前一个元素: " << *(--it) << endl; } system ("pause" ); return 0 ; }
类查找容器元素 find: 该算法不仅可以查询普通数据结构,还可以查询结构与类中数据.
#include <iostream> #include <vector> #include <string> #include <algorithm> using namespace std;class Person { public : string m_name; int m_age; public :Person (string name, int age){ this ->m_name = name; this ->m_age = age; } public : bool operator ==(const Person &p){ if (this ->m_name == p.m_name && this ->m_age == p.m_age) return true ; return false ; } }; int main (int argc, char * argv[]) { vector<Person> var; Person p1 ("aaa" , 10 ) ; Person p2 ("bbb" , 20 ) ; Person p3 ("ccc" , 30 ) ; var.push_back (p1); var.push_back (p2); var.push_back (p3); vector<Person>::iterator pos = find (var.begin (), var.end (), p1); if (pos != var.end ()) cout << "找到姓名: " << (*pos).m_name << endl; system ("pause" ); return 0 ; }
条件查找容器元素 find_if: 该查询与上方的普通查找相比,该查找可以添加回调函数,用于对查到的数据进行筛选.
#include <iostream> #include <vector> #include <algorithm> using namespace std;bool MyFunction (int x) { return x % 5 ? 0 : 1 ; }int main (int argc, char * argv[]) { vector<int > var (20 ) ; for (unsigned int x = 0 ; x < var.size (); x++) var[x] = (x + 1 ) * (x + 3 ); vector<int >::iterator it = find_if (var.begin (),var.end (),MyFunction); if (it != var.end ()) { cout << *it << endl; cout << "元素索引: " << it - var.begin () << endl; } system ("pause" ); return 0 ; }
条件查找类容器元素 find_if: 查找ptr
类中的数据,是否存在于我们的结构中.
#include <iostream> #include <vector> #include <string> #include <functional> #include <algorithm> using namespace std;class Person { public : string m_name; int m_age; public :Person (string name, int age){ this ->m_name = name; this ->m_age = age; } public : bool operator ==(const Person &p){ if (this ->m_name == p.m_name && this ->m_age == p.m_age) return true ; return false ; } }; class MyCompare :public binary_function<Person *,Person *,bool >{ public : bool operator () (Person *p1,Person *p2) const { if (p1->m_name == p2->m_name && p1->m_age == p2->m_age) return true ; return false ; } }; int main (int argc, char * argv[]) { vector<Person *> var; Person p1 ("aaa" , 10 ) ; Person p2 ("bbb" , 20 ) ; Person p3 ("ccc" , 30 ) ; var.push_back (&p1); var.push_back (&p2); var.push_back (&p3); Person *ptr = new Person ("bbb" , 20 ); vector<Person *>::iterator pos = find_if (var.begin (), var.end (), bind2nd (MyCompare (),ptr)); if (pos != var.end ()) cout << "找到姓名: " << (*pos)->m_name << endl; system ("pause" ); return 0 ; }
**邻近查找容器元素 adjacent_find:**用于查找相等或满足条件的相邻的重复的元素,找到了返回第一个位的迭代器.
#include <iostream> #include <list> #include <algorithm> using namespace std;bool MyFunction (int x,int y) { return (x - y) % 2 == 0 ? 1 : 0 ; }int main (int argc, char * argv[]) { list<int > ls {1 ,2 ,3 ,4 ,5 ,6 ,6 ,7 ,8 ,9 ,10 }; list<int >::iterator it = adjacent_find (ls.begin (), ls.end ()); if (it != ls.end ()) cout << *it << endl; it = adjacent_find (ls.begin (), ls.end (), MyFunction); if (it != ls.end ()) { cout << *it << endl; it++; cout << *it << endl; } system ("pause" ); return 0 ; }
范围查找容器元素 find_first_of: 该算法可用于查找位于某个范围之内的元素.
#include <iostream> #include <string> #include <algorithm> using namespace std;int main (int argc, char * argv[]) { char * str1 = "hello" ; char * str2 = "lyshark This is a test case. Thank you for using it lyshark." ; char * result = find_first_of (str1, str1 + strlen (str1), str2, str2 + strlen (str2)); cout << *result << endl; system ("pause" ); return 0 ; }
普通元素计数统计 count: 该算法用于计算容器中某个给定值得出现次数.
#include <iostream> #include <list> #include <algorithm> using namespace std;int main (int argc, char * argv[]) { list<int > ls; for (int x = 0 ; x < 100 ; x++) { ls.push_back (x % 20 ); } int num = 0 ; int value = 9 ; num = count (ls.begin (), ls.end (), value); cout << "The number of occurrences is: " << num << endl; system ("pause" ); return 0 ; }
条件元素计数统计 count_if: 与Count算法类似,该算法可以在统计前增加判断条件.
#include <iostream> #include <map> #include <algorithm> using namespace std;struct Student { struct Info { char *name; int year; }; int id; Info stu; Student (int _id, char *_name, int _year) { id = _id; stu.name = _name; stu.year = _year; } }; bool GetRange (pair<int , Student::Info> s) { if (s.second.year > 20 && s.second.year < 30 ) return 1 ; return 0 ; } int main (int argc, char * argv[]) { Student stu1 = Student (1 , "admin" , 10 ); Student stu2 = Student (2 , "guest" , 21 ); Student stu3 = Student (3 , "lyshark" , 35 ); map<int , Student::Info> mp; pair<int , Student::Info> pairSt1 (stu1.id, stu1.stu) ; mp.insert (pairSt1); pair<int , Student::Info> pairSt2 (stu2.id, stu2.stu) ; mp.insert (pairSt2); pair<int , Student::Info> pairSt3 (stu3.id, stu3.stu) ; mp.insert (pairSt3); int num = 0 ; num = count_if (mp.begin (), mp.end (), GetRange); cout << num << endl; system ("pause" ); return 0 ; }
二分法查找算法 binary_search: 该算法就是折半查找法,查找的元素集合必须是一个有序的序列.
#include <iostream> #include <vector> #include <algorithm> using namespace std;int main (int argc, char * argv[]) { vector<int > var{ 1 , 2 , 3 , 4 , 5 , 6 , 6 , 7 , 8 , 9 , 10 }; bool ret = binary_search (var.begin (), var.end (), 4 ); if (ret) cout << "found ok" << endl; else cout << "not found" << endl; system ("pause" ); return 0 ; }
元素不匹配查找 mismatch: 该算法函数比较两个序列,并从中找出首个不匹配元素的位置.
#include <iostream> #include <vector> #include <cstring> #include <algorithm> using namespace std;bool StrEqual (const char * x, const char * y) { return strcmp (x, y) == 0 ? 1 : 0 ; } int main (int argc, char * argv[]) { vector<int > var1{ 2 , 0 , 0 , 6 }; vector<int > var2{ 2 , 0 , 0 , 7 }; pair<vector<int >::iterator, vector<int >::iterator> result; result = mismatch (var1.begin (), var1.end (), var2.begin ()); if (result.first == var1.end () && result.second == var1.end ()) cout << "var1 与var2完全一致" << endl; else cout << "var1 = " << *result.first << " --> var2= " << *result.second << endl; char * str1[] = { "apple" , "pear" , "banana" , "grape" }; char * str2[] = { "apple" , "pear" , "banana" , "zoops" }; pair<char **, char **> result2 = mismatch (str1, str1 + 4 , str2, StrEqual); if (result2.first != str1 + 4 && result2.second != str2 + 4 ) { cout << "str1 = > " << str1[result2.first - str1] << endl << endl; cout << "str2 = > " << str2[result2.second - str2] << endl; } system ("pause" ); return 0 ; }
元素相等的判断 equal: 该算法实现逐一比较两个序列的元素是否相等,该函数不返回迭代器.
#include <iostream> #include <vector> #include <algorithm> using namespace std;bool absEqual (const int x,const int y) { return (x == abs (y) || abs (x) == y) ? 1 : 0 ; } int main (int argc, char * argv[]) { vector<int > var1; vector<int > var2; for (unsigned int x = 0 ; x < var1.size (); x++) { var1[x] = x; var2[x] = -1 * x; } if (equal (var1.begin (), var1.end (), var2.begin (), absEqual)) { cout << "完全相等" << endl; } system ("pause" ); return 0 ; }
子序列搜索算法 search: 该算法实现了在一个序列中搜索与另一个序列匹配的子序列.
#include <iostream> #include <vector> #include <algorithm> using namespace std;int main (int argc, char * argv[]) { vector<int > var1 = { 5 , 6 , 7 , 8 , 9 }; vector<int > var2 = { 7 , 8 }; vector<int >::iterator it; it = search (var1.begin (), var1.end (), var2.begin (),var2.end ()); if (it != var1.end ()) { cout << "Offset = " << it - var1.begin () << endl; } system ("pause" ); return 0 ; }
重复元素子序列搜索 search_n: 该算法搜索序列中是否有一系列元素值均为某个给定值得子序列.
#include <iostream> #include <vector> #include <algorithm> using namespace std;int main (int argc, char * argv[]) { vector<int > var1 = { 5 , 6 , 7 , 8 ,8 ,8 ,9 }; vector<int >::iterator it; it = search_n (var1.begin (), var1.end (), 3 , 8 ); if (it != var1.end ()) { cout << "var1中存在三连8" << endl; } system ("pause" ); return 0 ; }
最后一个子序列搜索 find_end: 该算法在一个序列中搜索出最后一个与另一个序列匹配的子序列.
#include <iostream> #include <vector> #include <algorithm> using namespace std;int main (int argc, char * argv[]) { vector<int > var1 = { -5 ,1 ,2 ,-6 ,-8 ,1 ,2 ,-11 }; vector<int > var2 = { 1 , 2 }; vector<int >::iterator it; it = find_end (var1.begin (), var1.end (), var2.begin (), var2.end ()); if (it != var1.end ()) cout << "offset = [" << it - var1.begin () << "]" << endl; system ("pause" ); return 0 ; }
STL 变易算法(复制与拷贝) C++ 变易算法是一组能够修改容器元素数据的模板函数,可进行序列数据的复制,交换,替换,分割,等特殊需求,这些算法对迭代器有较高的要求,具体的迭代器类型随各个算法而定,使用变易算法时应先要检查容器的迭代器是否符合要求,避免出现错误.
元素复制算法 copy: 实现容器之间元素的拷贝复制操作,将两个迭代器进行互相拷贝.
#include <iostream> #include <vector> #include <algorithm> using namespace std;void MyPrint (int x) { cout << x << " " ; }int main (int argc, char * argv[]) { vector<int > var1 = { 1 ,3 ,5 ,7 ,9 }; vector<int > var2 = { 2 ,4 ,6 ,8 ,10 }; copy (var1.begin (), var1.end (), var2.begin ()); for_each(var2.begin (), var2.end (), MyPrint); cout << endl; copy_backward (var1.begin (), var1.begin () + 2 , var1.end ()); for_each(var1.begin (), var1.end (), MyPrint); system ("pause" ); return 0 ; }
元素交换算法 swap: 该算法可用于实现两个数或两个结构之间数据的互换,使用非常方便.
#include <iostream> #include <vector> #include <algorithm> using namespace std;void MyPrint (int x) { cout << x << " " ; }int main (int argc, char * argv[]) { vector<int > var1 = { 1 ,3 ,5 ,7 ,9 }; vector<int > var2 = { 2 ,4 ,6 ,8 ,10 }; swap (var1, var2); for_each(var1.begin (), var1.end (), MyPrint); iter_swap (&var1, &var2); for_each(var2.begin (), var2.end (), MyPrint); swap_ranges (var1.begin (), var1.end (), var2.begin ()); for_each(var2.begin (), var2.end (), MyPrint); system ("pause" ); return 0 ; }
元素搬运算法 transform: 该算法用于实现容器元素的变换操作,例如两个容器相加等操作.
#include <iostream> #include <vector> #include <algorithm> using namespace std;void MyPrint (int x) { cout << x << " " ; }class TransForm { public : int operator () (int val) { return val + 10 ; } }; class New_TransForm { public : int operator () (int val1, int val2) { return val1 + val2; } }; int main (int argc, char * argv[]) { vector<int > var = { 1 ,2 ,3 ,4 ,5 }; vector<int > vTarget; vTarget.resize (5 ); transform (var.begin (), var.end (), vTarget.begin (), TransForm ()); for_each(vTarget.begin (), vTarget.end (), [](int val){cout << val << " " ; }); cout << endl; vector<int > var1 = { 1 , 2 , 3 , 4 , 5 }; vector<int > var2 = { 6 , 7 , 8 , 9 , 10 }; vector<int > new_vTarget; new_vTarget.resize (5 ); transform (var1.begin (), var1.end (), var2.begin (), new_vTarget.begin (), New_TransForm ()); for_each(new_vTarget.begin (), new_vTarget.end (), MyPrint); system ("pause" ); return 0 ; }
元素替换算法 replace: 该算法的作用是将指定元素的旧值替换为新值.
#include <iostream> #include <vector> #include <algorithm> using namespace std;void MyPrint (int x) { cout << x << " " ; }class MyCompart { public : bool operator () (int val) { return val > 5 ; } }; int main (int argc, char * argv[]) { vector<int > var = { 1 ,2 ,3 ,4 ,4 ,5 ,5 ,6 ,7 ,8 ,8 ,9 ,0 ,2 ,1 ,0 }; replace (var.begin (), var.end (), 4 , 4000 ); for_each(var.begin (), var.end (), MyPrint); replace_if (var.begin (), var.end (), MyCompart (), 0 ); for_each(var.begin (), var.end (), MyPrint); system ("pause" ); return 0 ; }
容器元素初始化算法 fill: 该函数将同一个值填充到容器的指定位置,可用于初始化操作.
#include <iostream> #include <vector> #include <algorithm> using namespace std;void MyPrint (int x) { cout << x << " " ; }int main (int argc, char * argv[]) { vector<int > var = { 1 ,2 ,3 ,4 ,4 ,5 ,5 ,6 ,7 ,8 ,8 ,9 ,0 ,2 ,1 ,0 }; fill_n (var.begin (), 3 , 0 ); for_each(var.begin (), var.end (), MyPrint); fill_n (var.begin (), var.size (), 0 ); for_each(var.begin (), var.end (), MyPrint); fill (var.begin (), var.end (), 10 ); for_each(var.begin (), var.end (), MyPrint); system ("pause" ); return 0 ; }
普通条件移除 remove_if: 该算法可以将容器中不等于某个值的元素移除出容器.
#include <iostream> #include <vector> #include <algorithm> using namespace std;void MyPrint (int x) { cout << x << " " ; }bool even (int val) { return val % 2 ? 0 : 1 ; }int main (int argc, char * argv[]) { vector<int > var { 4 ,3 ,4 ,8 ,9 ,5 ,6 ,7 ,8 ,9 ,2 ,1 ,4 }; vector<int >::iterator result; result = remove (var.begin (), var.end (), 4 ); for_each(var.begin (), var.end (), MyPrint); cout << endl; vector<int >::iterator result1; result1 = remove_if (var.begin (), var.end (), even); for_each(var.begin (), var.end (), MyPrint); system ("pause" ); return 0 ; }
条件移除复制 remove_copy: 该算法将原容器中不等于某个给定值的元素复制到新容器中.
#include <iostream> #include <vector> #include <algorithm> using namespace std;void MyPrint (int x) { cout << x << " " ; }bool even (int val) { return val % 2 ? 0 : 1 ; }int main (int argc, char * argv[]) { vector<int > var { 4 ,3 ,4 ,8 ,9 ,5 }; int iarray[6 ] = { 0 , 0 , 0 , 0 , 0 , 0 , }; remove_copy (var.begin (), var.end (), iarray, 4 ); for_each(iarray, iarray+6 , MyPrint); cout << endl; remove_copy_if (var.begin (), var.end (), iarray, even); for_each(iarray, iarray + 6 , MyPrint); system ("pause" ); return 0 ; }
容器元素去重算法 unique: 提供两个算法,unique_copy
实现邻近元素去重,unique
去除连续重复元素.
#include <iostream> #include <vector> #include <algorithm> using namespace std;void MyPrint (int x) { cout << x << " " ; }int main (int argc, char * argv[]) { vector<int > var { 2 ,5 ,5 ,5 ,5 ,5 ,6 ,7 ,5 ,9 ,5 }; int iarray[] = { 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 }; unique_copy (var.begin (), var.end (), iarray); for_each(iarray, iarray + 10 , MyPrint); cout << endl; vector<int >::iterator result; result = unique (var.begin (), var.end ()); for_each(var.begin (),result,MyPrint); system ("pause" ); return 0 ; }
元素反向拷贝算法 reverse: 该算法实现了对容器中元素的反向排列,和反向复制容器中的数据.
#include <iostream> #include <vector> #include <algorithm> using namespace std;void MyPrint (int x) { cout << x << " " ; }int main (int argc, char * argv[]) { vector<int > var { 1 ,2 ,3 ,4 ,5 ,6 ,7 ,8 ,9 ,10 }; reverse (var.begin (), var.end ()); for_each(var.begin (), var.end (), MyPrint); cout << endl; int iarray[10 ] = { 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 }; reverse_copy (var.begin (), var.end (), iarray); for_each(iarray,iarray+10 , MyPrint); system ("pause" ); return 0 ; }
容器旋转复制算法 rotate: 该算法用于旋转数值,需要指定一个中心数.
#include <iostream> #include <vector> #include <algorithm> using namespace std;void MyPrint (int x) { cout << x << " " ; }int main (int argc, char * argv[]) { vector<int > var { 1 ,2 ,3 ,4 ,5 ,6 ,7 ,8 ,9 ,10 }; for_each(var.begin (), var.end (), MyPrint); cout << "middle => " << *(var.begin () + 5 ) << endl; rotate (var.begin (), var.begin () + 5 , var.end ()); for_each(var.begin (), var.end (), MyPrint); cout << endl; int iarray[10 ] = { 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 }; rotate_copy (var.begin (), var.begin () + 5 , var.end (), iarray); for_each(iarray,iarray+10 , MyPrint); system ("pause" ); return 0 ; }
随机数相关算法 random: 算法generate_n
用于生成随机数,random_shuffle
用于打乱数组.
#include <iostream> #include <vector> #include <ctime> #include <algorithm> using namespace std;void MyPrint (int x) { cout << x << " " ; }int main (int argc, char * argv[]) { srand ((unsigned int )time (NULL )); vector<int > var (10 ) ; generate_n (var.begin (), 5 , rand); for_each(var.begin (), var.end (), MyPrint); cout << endl; int iarray[10 ] = { 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 }; random_shuffle (iarray, iarray + 10 ); for_each(iarray, iarray + 10 , MyPrint); system ("pause" ); return 0 ; }
容器元素分割算法 partition: 该算法用于重新分割排列容器的元素,第一种无序分割,第二种为有序分割.
#include <iostream> #include <vector> #include <algorithm> using namespace std;void MyPrint (int x) { cout << x << " " ; }bool Less (int y) { return y < 10 ? 1 : 0 ; } int main (int argc, char * argv[]) { int iarray[10 ] = { 12 ,45 ,2 ,6 ,8 ,-5 ,-12 ,-78 ,-4 ,3 }; int * result = partition (iarray, iarray + 10 , Less); for_each(iarray, result , MyPrint); cout << endl; int * new_ret = stable_partition (iarray, iarray + 10 , Less); for_each(iarray, iarray + 10 , MyPrint); cout << " --> 分界元素 Mid:" << *new_ret << endl; system ("pause" ); return 0 ; }