参考教程: cpp-STL - AlgorithmPark 基本上是转载,跟着写了一遍理思路。
1. vector 容器 头文件 #include<vector>
(1)构造 1 2 3 4 5 6 7 8 9 10 11 12 13 #include <iostream> #include <vector> using namespace std;vector<int >b; vector<int >a (10 ); vector<int >a (10 ,1 ); vector<int >a (b); vector<int >a (b.begin (),b.begin ()+3 ); int c[7 ]={1 ,2 ,3 ,4 ,5 ,6 ,7 };vector<int >a (c,c+7 ); vector<int >a{1 ,2 ,3 ,4 ,5 ,6 ,7 }; vector<int >a={1 ,2 ,3 ,4 ,5 ,6 ,7 };
(2)基本操作 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 void test01 () { vector<int > a, b; int i=0 ; a.assign (b.begin (), b.begin () + 3 ); a.assign (4 , 2 ); a.back (); a.front (); a[i]; a.clear (); a.empty (); a.pop_back (); a.erase (a.begin () + 1 , a.begin () + 3 ); a.push_back (5 ); a.insert (a.begin () + 1 , 5 ); a.insert (a.begin () + 1 , 3 , 5 ); int d[8 ]; a.insert (a.begin () + 1 , d + 3 , d + 6 ); a.size (); a.capacity (); a.resize (10 ); a.resize (10 , 2 ); a.reserve (100 ); a.swap (b); a == b; }
assign
赋值
insert
插入
resize
调整
reserve
扩充
(3)反向迭代 1 2 3 4 5 6 7 8 void test02 () { vector<int >a={1 ,2 ,3 ,4 ,5 ,6 ,7 ,8 ,9 ,10 }; for (vector<int >::reverse_iterator iter=a.rbegin ();iter!=a.rend ();iter++) { cout<<*iter<<endl; } }
(4)插入
描述
函数签名
插入位置都在 pos
迭代器之前一个位置,返回的迭代器指向插入的第一个元素
在迭代器 pos
指定的位置之前插入一个新元素 elem
,并返回表示新插入元素位置的迭代器
iterator insert(pos, elem)
在迭代器 pos
指定的位置之前插入 n
个元素 elem
,并返回表示第一个新插入元素位置的迭代器
iterator insert(pos, n, elem)
在迭代器 pos
指定的位置之前,插入其他容器中位于 [first, last)
区域的所有元素,并返回表示第一个新插入元素位置的迭代器
iterator insert(pos, first, last)
在迭代器 pos
指定的位置之前,插入初始化列表(用大括号 {} 括起来的多个元素),中间有逗号隔开)中的所有的元素,并返回表示第一个新插入元素位置的迭代器
iterator insert(pos, initlist)
1 2 3 4 5 6 7 8 9 10 11 12 void test03 () { vector<int >a={1 ,2 ,3 ,4 ,5 ,6 ,7 ,8 ,9 ,10 }; vector<int >::iterator it1=a.begin ()+4 ; vector<int >::iterator it2=a.insert (it1,{-1 ,-2 ,-3 }); cout<<*it2<<endl; for (auto k:a) { cout<<k<<" " ; } cout<<endl; }
(5)
函数
说明
pop_back()
删除 vector 容器中最后一个元素,该容器的大小(size)会减 1,但容量 (capacity) 不会发生改变。
erase(pos)
删除 vector 容器中 pos 迭代器指定位置处的元素,并返回指向被删除元素下一个位置的迭代器。该容器的大小 (size) 会减 1,但容量 (capacity) 不会发生改变。
???swap(beg)、pop_back ()
先调用 swap() 函数交换要删除的目标元素和容器最后一个元素的位置,然后使用 pop_back () 删除该目标元素。
erase(beg,end)
删除 vector 容器中位于迭代器 [beg, end) 指定区域内的所有元素,并返回指向被删除区域下一个位置元素的迭代器。该容器的大小 (size) 会减小,但容量 (capacity) 不会发生改变。
remove()
删除容器中所有和指定元素值相等的元素,并返回指向最后一个元素下一个位置的迭代器。值得一提的是,调用该函数不会改变容器的大小和容量。
clear()
删除 vector 容器中所有的元素,使其变成空的 vector 容器。该函数会改变 vector 的大小 (变为 0),但不是改变其容量。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 void test04 () { vector<int >a = { 1 ,2 ,3 ,4 ,5 ,6 ,6 ,6 ,6 ,7 ,8 ,9 ,10 }; int size = a.size (); ptrdiff_t cnt = count (a.begin (), a.end (), 6 ); auto it = remove (a.begin (), a.end (), 6 ); cout << *it << endl; cout << cnt << endl; for (auto k : a) { cout << k << " " ; } cout << endl; a.resize (size - cnt); for (auto k : a) { cout << k << " " ; } }
2.deque 容器 头文件 #include<deque
(1)遍历容器 1 2 3 4 5 6 7 8 9 10 void printdeque (const deque<int >& d) { for (deque<int >::const_iterator it=d.begin ();it!=d.end ();it++) { cout<<*it<<" " ; } cout<<endl; }
(2)构造容器 1 2 3 4 5 6 7 8 9 10 11 12 13 14 void test01 () { deque<int >d1; for (int i = 0 ; i < 10 ; i++) d1.push_front (i+1 ); printdeque (d1); deque<int >d2 (d1.begin (), d1.end ()); printdeque (d2); deque<int >d3 (10 , 100 ); printdeque (d3); deque<int >d4 (d3); printdeque (d4); }
程序输出:
1 2 3 4 10 9 8 7 6 5 4 3 2 1 10 9 8 7 6 5 4 3 2 1 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100 100
(3)赋值操作 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 void test03 () { deque<int >d1; for (int i=0 ;i<10 ;i++) { d1.push_back (i+1 ); } printdeque (d1); deuqe<int >d2; d2=d1; printdeque (d2); deque<int >d3; d3.assgin (d1.begin (),d1.end ()); printdeque (d3); deque<int >d4; d4.assign (10 ,100 ); printdeque (d4); }
程序输出:
1 2 3 4 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 100 100 100 100 100 100 100 100 100 100
(4)插入和删除 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 #include <iostream> #include <deque> using namespace std;void printDeque (const deque<int >& d) { for (int elem : d) { cout << elem << " " ; } if (d.empty ()) { cout << "(empty)" ; } cout << endl; } void testDequeOperations () { deque<int > d; d.push_front (10 ); d.push_front (20 ); d.push_front (30 ); printDeque (d); d.push_back (40 ); d.push_back (50 ); printDeque (d); d.insert (d.begin () + 2 , 100 ); d.insert (d.end () - 1 , 2 , 200 ); printDeque (d); d.pop_front (); printDeque (d); d.pop_back (); printDeque (d); d.erase (d.begin () + 1 ); printDeque (d); d.erase (d.begin () + 2 , d.end () - 1 ); printDeque (d); d.clear (); printDeque (d); } int main () { testDequeOperations (); return 0 ; } }
(5)数据存取 1 2 3 4 5 6 7 deque d1; d1[2 ]; d1.at (2 ); d1.front (); d1.back ();
3. stack 容器 头文件 #include<stack>
后进先出
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 void test01 () { stack<int >s; s.push (10 ); s.push (20 ); s.push (30 ); s.push (40 ); int n=s.size (); for (int i=0 ;i<n;i++) { cout<<s.top ()<<" " ; s.pop (); } cout<<endl; }
4. queue 容器 头文件 #include<queue>
先进先出
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 #include <queue> using namespace std;void testqueue () { queue<int >q; q.push (10 ); q.push (20 ); q.push (30 ); queue<int >temp=q; while (!q.empty ()) { cout<<temp.front ()<<" " ; q.pop (); } cout<<endl; cout<<q.front ()<<q.back ()<<endl; cout<<q.empty ()<<endl; cout<<q.size ()<<endl; while (!q.empty ()) { q.pop (); } } int main () { testqueue (); return 0 ; }
5. string 容器 (1)构造 1 2 3 4 5 6 7 8 9 10 11 12 void test01{ string s1; cout<<"s1=" <<s1<<endl; const char * str= "hello world!" string s2 (str); cout<<"s2=" <<s2<<endl; string s3 (s2) ; cout<<"s3=" <<s3<<endl; string s4 (10 ,'b' ) ; cout<<"s4=" <<s4<<endl; }
1 2 3 4 s1= s2=hello world! s3=hello world! s4=bbbbbbbbbb
(2)赋值 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 void test01{ string str1; str1="hello world!" ; cout<<"str1=" <<str1<<endl; string str2=str1; cout<<"str2=" <<str2<<endl; string str4; str4.assign ("hello" ); cout<<"str4=" <<str4<<endl; string str5; str5.assign ("hello" ,3 ); cout<<"str5=" <<str5<<endl; string str6; str6.assign (str5); string str7; str7.assign (10 ,'w' ); }
(3)拼接 1 2 3 4 5 6 7 8 9 10 11 string s1="你" ; s1+="好" ; string s2="我也爱C语言" ; s1.append (s2,4 ,7 ); cout<<"s1=" <<s1<<endl;
"我"
(索引 0
,长度 1
)占两个字节。
"也"
(索引 1
,长度 1
)占两个字节。
"爱"
(索引 2
,长度 1
)占两个字节。
"C"
(索引 3
,长度 1
)占一个字节。
"语"
(索引 4
,长度 1
)占两个字节。
"言"
(索引 5
,长度 1
)占两个字节。
(4)查找和替换 1 2 3 4 5 6 string s="abcdefgdefg" ; int pos1=s.find ("de" );int pos2=s.find ("df" );int pos3=s.rfind ("df" );s.replace (1 ,3 ,"1111" );
(5)字符串比较 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 void test01 () { string str1 = "hfllo" ; string str2 = "hello" ; if (str1.compare (str2) == 0 ) { cout << "str1等于str2" << endl; } else if (str1.compare (str2) > 0 ) { cout << "str1大于str2" << endl; } else { cout << "str1小于str2" << endl; } }
数字 0-9 :48-57
大写字母 A-Z :65-90
小写字母 a-z :97-122
(6)字符提取 1 2 3 4 5 6 string str = "hello" ; for (int i = 0 ; i < 5 ; i++) cout << str[i] << " " ; cout << endl; for (int i = 0 ; i < 5 ; i++) cout << str.at (i) << " " ;
(7)插入和删除 1 2 3 4 5 string s1="abcdefgh" ; s1.insert (2 ,"xxx" ); s1.erase (2 ,3 ); s1.insert (2 ,3 ,'x' ); s1.insert (2 ,3 ,'x' );
(8)子串 1 2 3 string s1="abd*cdf" ; int pos=s1.find ('*' );string s2=s1.substr (0 ,pos);
(9)其他
string s; // 生成一个空字符串s
string s(str); // 拷贝构造函数生成str的复制品
string s(str, stridx); // 将字符串str内”始于位置stridx”的部分当作字符串的初值
string s(str, stridx, strlen); // 将字符串str内”始于stridx且长度顶多strlen”的部分作为字符串的初值
string s(cstr); // 将C字符串(以NULL结束)作为s的初值
string s(chars, chars_len); // 将C字符串前chars_len个字符作为字符串s的初值。
string s(num, ‘c’); // 生成一个字符串,包含num个c字符
string s(“value”); string s = “value”; // 将s初始化为一个字符串字面值副本
string s(begin, end); // 以区间begin/end(不包含end)内的字符作为字符串s的初值
s.~string(); //销毁所有字符,释放内存
string s;
s.empty(); // s为空串 返回true
s.size(); // 返回s中字符个数 类型应为:string::size_type
s[n]; // 从0开始相当于下标访问
s1+s2; // 把s1和s2连接成新串 返回新串
s1=s2; // 把s1替换为s2的副本
v1 == v2
; // 比较,相等返回true
!=, <, <=, >, >=
惯有操作 任何一个大写字母都小于任意的小写字母
1 2 3 string s ("abc" ) ;s.size (); strlen (s.c_str ());
1 2 3 4 5 6 7 string s = "abcdefg" ; char str[1000 ]; strcpy (str, s.c_str ()); str[0 ] = 'p' ; str[5 ] = 'u' ; }
6. set 容器和 multiset 容器 #include<set>
set不允许容器中有重复的元素 multiset允许容器中有重复的元素 其他操作基本一致
(1)遍历容器 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 #include <iostream> #include <set> using namespace std;void printset (const set<int >&s) { if (s.empty ()) { cout<<"set数组为空" <<endl; return ; } for (set<int >::const_iterator it=s.begin ();it!=s.end ();it++) { cout<<*it<<" " ; } cout<<endl; } void printmultiset (const multiset<int >&m) { if (m.empty ()) { cout<<"multiset数组为空" <<endl; return ; } for (multiset<int >::const_iterator it=m.begin ();it!=m.end ();it++) { cout<<*it<<" " ; } cout<<endl; }
(2)插入和删除 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 set<int >s; s.insert (10 ); s.insert (20 ); s.insert (30 ); s.insert (40 ); s.insert (50 ); s.insert (60 ); s.insert (70 ); s.insert (80 ); s.insert (90 ); s.insert (100 ); s.insert (110 ); s.insert (120 ); printset (s);set<int >::iterator it=s.begin (); set<int >::iterator it2; it2=s.erase (++++it); printset (s);set<int >::iterator it1=s.end (); s.erase (it2,----it1); printset (s);s.erase (110 ); printset (s);s.clear (); printset (s);
(2)查找和统计 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 set<int >s; s.insert (10 ); s.insert (20 ); s.insert (30 ); s.insert (40 ); s.insert (30 ); s.insert (60 ); s.insert (70 ); s.insert (80 ); s.insert (70 ); s.insert (100 ); s.insert (110 ); s.insert (120 ); printset (s);set<int >::()iterator it1; it1=s.find (70 ); if (it1!=s.end ()) cout<<*it<<endl;else cout<<"未找到元素" <<endl;int num=s.count (30 );cout<<num<<endl;
程序输出:
1 2 3 10 20 30 40 60 70 80 100 110 120 70 1
(4)set 与 multiset 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 set<int >s; s.insert (20 ); s.insert (20 ); s.insert (30 ); s.insert (40 ); s.insert (30 ); s.insert (60 ); s.insert (70 ); s.insert (80 ); s.insert (70 ); s.insert (100 ); s.insert (110 ); s.insert (120 ); printset (s);pair<set<int >::iterator,bool >ret =s.insert (10 ); if (ret.second) cout<<"第一次插入成功" <<endl;else cout<<"第一次插入失败" <<endl;pair<set<int >::iterator,bool >ret1 =s.insert (10 ); if (ret1.second) cout<<"第二次插入成功" <<endl;else cout<<"第二次插入失败" <<endl;
输出:
1 2 3 20 30 40 60 70 80 100 110 120 第一次插入成功 第二次插入失败
7. map 和 multimap 容器 头文件 #include<map>
map 中所有元素都是 pair, 第一个元素为 key (键值), 起到索引作用, 第二个元素为 value(实值) 所有元素都有根据元素键值自动排序
map/multimap属于关联式容器,底层结构是用二叉树实现 优点:可以根据key值快速找到value值 map和multimap区别: map不允许容器中有重复key值元素 multimap允许容器中有重复key值元素
(1)遍历 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 #include <iostream> #include <map> using namespace std;void printmap (const map<int ,int >&m) { if (m.empty ()) { cout<<"map容器为空" <<endl; return ; } for (map<int ,int >::const_iterator it=m.begin ();it!=m.end ();it++) { cout<<"学号:" <<(*it).first<<" 分数:" <<(*it).second<<endl; } cout<<endl; } void test01 () { map<int ,int >m; m.insert (pair <int ,int >(1 ,60 )); m.insert (pair <int ,int >(2 ,95 )); m.insert (pair <int ,int >(4 ,73 )); m.insert (pair <int ,int >(3 ,81 )); printmap (m); map<int ,int >m2 (m); printmap (m2); map<int ,int >m3; m3=m2; printmap (m3); }
(2)大小和转换 1 2 3 4 map<int ,int >ma; ma.size (); map<int ,int >ma1; ma.swap (ma1);
(3)插入和删除 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 map<int ,int >m; m.insert (pair <int ,int >(1 ,60 )); m.insert (pair <int ,int >(3 ,95 )); m.insert (pair <int ,int >(4 ,73 )); m.insert (pair <int ,int >(5 ,81 )); m.insert (make_pair (2 ,10 )); m.insert (map<int ,int >::value_type (6 ,30 )); m[7 ]=40 ; printmap (m);m.erase (m.begin (),++++m.begin ()); printmap (m);m.erase (4 ); printmap (m);m.clear (); printmap (m);
程序输出:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 学号:1 分数:60 学号:2 分数:10 学号:3 分数:95 学号:4 分数:73 学号:5 分数:81 学号:6 分数:30 学号:7 分数:40 学号:3 分数:95 学号:4 分数:73 学号:5 分数:81 学号:6 分数:30 学号:7 分数:40 学号:3 分数:95 学号:5 分数:81 学号:6 分数:30 学号:7 分数:40
(4)查找和统计 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 map<int ,int >m; m.insert (pair <int , int >(1 ,60 )); m.insert (pair <int , int >(3 , 95 )); m.insert (pair <int , int >(4 , 73 )); m.insert (pair <int , int >(5 , 81 )); m.insert (pair <int , int >(2 , 84 )); map<int ,int >::iterator it; it=m.find (4 ); if (it!=m.end ()){ cout<<it->second<<endl; } else { cout<<"编号不存在" <<endl; } cout<<m.count (4 )<<endl;
8. priority_queue 头文件 #include<queue>
priority_queue
是一个元素有序排列的队列,默认队列头部元素优先级最高。因为是一个队列,只能访问第一个元素,这也意味着优先级最高的元素总是第一个被处理。它能够实现常数时间的(默认)最大元素查找,对数代价的插入与释出
(1)构造 1 2 priority_queue<int >pq1; priority_queue<int ,vector<int >,greater<int >>pq2;
priority_queue
有三个模板参数:元素类型(T
),底层容器类型(Container
,默认为 vector<T>
),以及比较方式(Compare
,默认为 std::less<T>
)。
默认构造的 priority_queue
(priority_queue<int>
) 是一个最大堆 ,其中最大的元素在堆顶。
通过使用 std::greater<int>
作为比较对象 (priority_queue<int, vector<int>, greater<int>>
),你可以创建一个最小堆 ,其中最小的元素在堆顶。
(2)元素访问 top () 访问栈顶元素
1 2 3 4 5 6 7 8 9 10 11 12 #include <iostream> #include <queue> using namespace std;int main () { priority_queue<int ,vector<int >,less<int >>pq1; pq1.push (10 ); pq1.push (40 ); pq1.push (20 ); cout<<pq1.top ()<<endl; return 0 ; }
(3)容量 empty () size ()
(4)修改器 push 插入元素并排序 pop 删除队首元素并排序
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 #include <iostream> #include <queue> using namespace std;int main () { priority_queue<int >pq1; pq1.push (10 ); pq1.push (40 ); pq1.push (20 ); pq1.push (30 ); while (!pq1.empty ()) { cout<<pq1.top ()<<" " ; pq1.pop (); } return 0 ; }
9. STL 常用算法 下面基本上都需要 #include<algorithm>
头文件
1 2 3 4 5 6 7 8 9 10 vector<int >v; for (int i=0 ;i<10 ;i++){ v.push_back (i+1 ); } vector<int >vtarget; vtarget.resize (v.size ()); transform (v.begin (), v.end (), vtarget.begin (), Transform ());for_each(vtarget.begin (), vtarget.end (), myprint ());
v.begin(), v.end()
:表示要转换的输入范围是 v
的起始到末尾。
vtarget.begin()
:表示转换后的结果要放到 vtarget
中,从其开始位置存储。
Transform()
:这是一个函数对象 或仿函数 ,用于指定要对输入范围的每个元素执行的操作。假定的 Transform
类
Transform
需要是一个函数对象,类似于:
1 2 3 4 5 6 struct Transform {int operator () (int val) const { return val + 100 ; } };
该类重载了 operator()
,使得 Transform
类的对象能够像函数一样被调用。
在 transform
函数中,每次调用 Transform()
时,都会对输入的元素执行 val + 100
的操作。
因此,v
中的每个元素 1, 2, ..., 10
将被转换为 101, 102, ..., 110
,并存储在 vtarget
中。
for_each
是 C++ 标准库中的另一个算法,用于对范围内的每个元素执行某个操作。
这行代码的参数:
vtarget.begin(), vtarget.end()
:表示对 vtarget
的所有元素执行操作。
myprint()
:这是另一个函数对象,用于指定对每个元素要执行的操作。假定的 myprint
类
myprint
需要是一个函数对象,类似于:
1 2 3 4 5 6 struct myprint { void operator () (int val) const { cout << val << " " ; } };
该类重载了 operator()
,使得 myprint
类的对象可以像函数一样被调用。
函数
说明
find
查找元素
find_if
按条件查找元素
adjacent_find
查找相邻重复元素
binary_search
二分查找法
count
统计元素个数
count_if
按条件统计元素个数
(2)find
find
用于查找指定元素 。
如果在指定的范围内找到了目标元素,它会返回指向该元素的迭代器 。
如果找不到目标元素,则返回一个**结束迭代器 (end()
)**,表示目标元素不在该范围内。 函数原型1 iterator find (iterator beg, iterator end, const T& value) ;
iterator beg
: 开始迭代器,表示查找范围的起点(包括 beg
)。
iterator end
: 结束迭代器,表示查找范围的终点(不包括 end
本身)。
value
: 要查找的目标值,函数将在 [beg, end)
范围内寻找该值。1 2 3 4 5 6 7 8 9 10 11 12 13 14 vector<int >v; for (int i=0 ;i<10 ;i++){ v.push_back (i+1 ); } vector<int >::iterator it=find (v.begin (),v.end (),5 ); if (it==v.end ()){ cout<<"未找到" <<endl; } else { cout<<"找到:" <<*it<<endl; }
(3)find_if 功能描述: 按条件查找元素 函数原型: find_if(iterator beg, iterator end, _Pred);
按值查找元素,找到返回指定位置选代器,找不到返回结束选代器位置 beg开始迭代器 end结束迭代器_Pred
函数或者谓词(返回bool类型的仿函数)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 class mycompare { public : bool operator () (int a) { return a > 5 ; } }; void test01 () { vector<int >v; for (int i = 0 ; i < 10 ; i++) v.push_back (i + 1 ); vector<int >::iterator it = find_if (v.begin (), v.end (), mycompare ()); if (it == v.end ()) cout << "未找到" << endl; else cout << "找到" << *it << endl; }
(4)binary_search 查找指定的元素,查到返回true,否则返回false 注意:在无序序列中不可用,因为结果会出错 降序也不行,只能用于升序 序列
1 2 3 4 5 vector<int >v={0 ,1 ,2 ,3 ,4 ,5 ,6 ,7 ,8 }; if (binary_search (v.begin (), v.end (), 6 )) cout << "找到了" << endl; else cout << "未找到" << endl;
(5)adjacent_find 查找相邻重复元素,返回相邻元素的第一个位置的迭代器
1 2 3 4 5 6 vector<int >v={0 ,2 ,0 ,3 ,1 ,4 ,3 ,3 ,2 }; vector<int >::iterator pos = adjacent_find (v.begin (), v.end ()); if (pos == v.end ()) cout << "未找到" << endl; else cout << *pos << endl;
(6)count 统计元素个数
1 2 3 vector<int >v={0 ,1 ,2 ,3 ,5 ,3 ,3 ,6 ,8 }; int cou = count (v.begin (), v.end (), 3 ); cout << cou << endl;
(7)count_if 1 2 3 4 5 6 7 8 9 10 11 12 13 14 class greaterfive { public : bool operator () (int a) { return a > 5 ; } }; void test01 () { vector<int >v={0 ,1 ,2 ,7 ,5 ,6 ,3 ,6 ,8 }; int cou = count_if (v.begin (), v.end (), greaterfive ()); cout << cou << endl; }
(8)sort 排序算法 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 void myprint (int val) { cout << val << " " ; } void test01 () { vector<int >v={10 ,30 ,50 ,20 ,40 ,90 }; for_each(v.begin (), v.end (), myprint); cout << endl; sort (v.begin (), v.end ()); for_each(v.begin (), v.end (), myprint); cout << endl; sort (v.begin (), v.end (), greater <int >()); for_each(v.begin (), v.end (), myprint); cout << endl; }
(9)random_shuffle 1 2 3 srand ((unsigned int )time (NULL )); vector<int >v={0 ,1 ,2 ,3 ,4 ,5 ,6 ,7 ,8 ,9 }; random_shuffle (v.begin (), v.end ());
在 C++11 及更高版本中,推荐使用 std::shuffle
替代 random_shuffle
1 2 3 4 5 6 7 8 9 10 11 #include <algorithm> #include <random> int main () { std::vector<int > v = {0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 }; std::random_device rd; std::default_random_engine rng (rd()) ; std::shuffle (v.begin (), v.end (), rng); return 0 ; }
(10)merge 可以把两个有序序列合在一起,形成一个新的有序序列
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 void myprint (int val) { cout << val << " " ; } void test01 () { vector<int >v1; vector<int >v2; for (int i = 0 ; i < 10 ; i++) { v1.push_back (i); v2.push_back (i + 1 ); } vector<int >vTarget; vTarget.resize (v1.size () + v2.size ()); merge (v1.begin (), v1.end (), v2.begin (), v2.end (), vTarget.begin ()); for_each(vTarget.begin (), vTarget.end (), myprint); cout << endl; }
(11)reverse 逆序
1 2 3 4 5 6 7 8 9 10 11 12 13 void myprint (int val) { cout<<val<<endl; } void test () { vector<int >v={10 ,30 ,40 ,50 ,20 }; for_each(v.begin (),v.end (),myprint); cout<<endl; reverse (v.begin (),v.end ()); for_each(v.begin (),v.end (),myprint); cout<<endl; }
(12)copy 将容器内指定范围的元素拷贝到另一容器中 注意:新容器需要预留空间
1 2 3 4 5 6 7 8 9 10 11 12 13 void mypriny (int val) { cout<<val<<endl; } void test () { vector<int >v={10 ,30 ,40 ,50 ,20 }; vector<int >v2; v2.resize (v.size ()); copy (v.begin (),v.end (),v2.begin ()); for_each(v2.begin (),v2.end (),myprint); cout<<endl; }
(13)replace 和 replace_if replace将容器内指定范围的旧元素修改为新元素 replace_if将区间内满足条件替换成指定元素
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 void myprint (int val) { cout << val << " " ; } class compare { public : bool operator () (int a) { return a >= 40 ; } }; void test01 () { vector<int >v={10 ,30 ,40 ,30 ,20 ,10 ,30 ,40 ,50 ,20 }; for_each(v.begin (), v.end (), myprint); cout << endl; replace (v.begin (), v.begin () + 4 , 30 , 300 ); for_each(v.begin (), v.end (), myprint); cout << endl; replace_if (v.begin (), v.end (), compare (), 66 ); for_each(v.begin (), v.end (), myprint); cout << endl; }
(14)swap 交换
1 2 3 4 5 6 vector<int >v={10 ,30 ,40 ,30 ,20 ,10 ,30 ,40 ,50 ,20 }; vector<int >v1; for (int i = 0 ; i < 10 ; i++) v1.push_back (i + 1 );swap (v, v1); for_each(v.begin (), v.end (), myprint); cout << endl;
(15)accumulate 和 fill #include<numeric>
accumulate计算容器元素累计总和 fill向容器中添加元素
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 void myprint (int val) { cout << val << " " ; } void test01 () { vector<int >v{10 ,30 ,40 ,30 ,20 ,10 ,30 ,40 ,50 ,20 }; for_each(v.begin (), v.end (), myprint); cout << endl; int total=accumulate (v.begin (), v.end (), 0 ); cout << total << endl; } void test02 () { vector<int >v; v.resize (10 ); for_each(v.begin (), v.end (), myprint); cout << endl; fill (v.begin (), v.end () - 2 , 6 ); for_each(v.begin (), v.end (), myprint); cout << endl; }
输出:
1 2 3 4 10 30 40 30 20 10 30 40 50 20 2800 0 0 0 0 0 0 0 0 0 6 6 6 6 6 6 6 6 0 0
(16)交集,并集,差集 set_intersection求两个容器的交集 set_union并集 set_difference差集
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 #include <iostream> #include <vector> #include <algorithm> using namespace std;void printVector (const vector<int >& v) { for (int val : v) { cout << val << " " ; } cout << endl; } int main () { vector<int > v1 = {1 , 2 , 3 , 4 , 5 , 6 }; vector<int > v2 = {4 , 5 , 6 , 7 , 8 , 9 }; vector<int > result; result.resize (min (v1.size (), v2.size ())); auto it = set_intersection (v1.begin (), v1.end (), v2.begin (), v2.end (), result.begin ()); result.resize (it - result.begin ()); cout << "Intersection of v1 and v2: " ; printVector (result); result.clear (); result.resize (v1.size () + v2.size ()); it = set_union (v1.begin (), v1.end (), v2.begin (), v2.end (), result.begin ()); result.resize (it - result.begin ()); cout << "Union of v1 and v2: " ; printVector (result); result.clear (); result.resize (v1.size ()); it = set_difference (v1.begin (), v1.end (), v2.begin (), v2.end (), result.begin ()); result.resize (it - result.begin ()); cout << "Difference of v1 and v2 (v1 - v2): " ; printVector (result); result.clear (); result.resize (v2.size ()); it = set_difference (v2.begin (), v2.end (), v1.begin (), v1.end (), result.begin ()); result.resize (it - result.begin ()); cout << "Difference of v2 and v1 (v2 - v1): " ; printVector (result); return 0 ; }
(17)next_premutation 全排列
1 2 3 4 5 6 7 8 9 10 11 12 13 14 vector<int >vec; for (int i = 0 ; i < 3 ; i++) { vec.emplace_back (i + 1 ); } for (auto k : vec) cout << k << " " ; cout << endl; while (next_permutation (vec.begin (), vec.end ())) { for (auto k : vec) cout << k << " " ; cout << endl; }
next_permutation
是 C++ <algorithm>
头文件中的一个函数,用于生成从当前排列组合的下一个字典序排列。
如果当前的排列组合已经是最大的排列组合,则 next_permutation
会返回 false
,否则返回 true
。
需要注意,next_permutation
只能在有序 的容器上工作,因此 vec
必须按升序(或其他顺序)排列才能生成所有排列组合。 输出:1 2 3 4 5 6 1 2 3 1 3 2 2 1 3 2 3 1 3 1 2 3 2 1
(18)lower_bound 和 upper_bound lower_bound( )和upper_bound( )都是利用二分查找的方法在一个排好序的数组中进行查找的。
在从小到大的排序数组中,lower_bound( begin,end,num):从数组的begin位置到end-1位置二分查找第一个大于或等于num的数字,找到返回该数字的地址,不存在则返回end。通过返回的地址减去起始地址begin,得到找到数字在数组中的下标。
upper_bound( begin,end,num):从数组的begin位置到end-1位置二分查找第一个大于num的数字,找到返回该数字的地址,不存在则返回end。通过返回的地址减去起始地址begin,得到找到数字在数组中的下标。
也可以用于vector容器,返回值是迭代器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 #include <iostream> #include <algorithm> using namespace std;int cmd (int a, int b) { return a > b; } int main () { int num[6 ] = { 1 , 2 , 4 , 7 , 15 , 34 }; sort (num, num + 6 ); int pos1 = lower_bound (num, num + 6 , 7 ) - num; cout << pos1 << " " << num[pos1] << endl; int pos2 = upper_bound (num, num + 6 , 7 ) - num; cout << pos2 << " " << num[pos2] << endl; sort (num, num + 6 , cmd); int pos3 = lower_bound (num, num + 6 , 7 , greater <int >()) - num; cout << pos3 << " " << num[pos3] << endl; int pos4 = upper_bound (num, num + 6 , 7 , greater <int >()) - num; cout << pos4 << " " << num[pos4] << endl; return 0 ; }