ACM常用的C++ && STL
内容
c++输入输出
1 #include <iostream> //c++输入输出的头文件 2 using namespace std; //名称空间, 不懂死记硬背 3 4 int main(){ 5 int a; //或是long long a; double a; char a[10]; 等等,总之不需要像c语言一样要占位符 6 cin >> a; //输入 7 cout << a; //输出 8 9 cout << "abcdefg"; //输出字符串 10 cout << endl; //换行 11 cout << "abcdefg" << endl; //合并cout,效果和上面两个语句一样 12 13 int b; 14 cin >> a >> b; //合并cin,效果和 cin >> a; cin >> b; 一样 15 cout << "abcdefg\n"; //效果和上一个语句一样 16 cout << 'a'; //输出字母a,而不是ASCII码,这个和c语言有点不一样 17 18 return 0; 19 }
在这里我们可以看到,用c++输入输出能够极大方面减少错误率,而且支持的对象也非常多(把上面的int a改成double a / long long a等等都是可以的),c语言的输入输出实在是有点麻烦。不过c语言的输入输出优点也是有的:格式化输出 printf(); 更方便,而且效率更高(比c++的输入输出要快)。所以,一般情况可以直接用c++的输入输出,而对于数据输入量大的题目最好改成c语言的输入输出。另外,如果想在c++中用c的头文件,只需要把 #include <xxx.h> 改成 #include <cxxx> 。举个例子,c语言中的输入输出头文件是 #include <stdio.h>,那么在c++中就是 #include <cstdio>。
c++ string
string类:这个就是升级版的 char s[] 。顾名思义,就是字符串,但是这个字符串比 char s[] 方便很多。我们先来看看string的头文件和名称空间:
1 #include <string> 2 using namespace std;
是不是又看到了 using namespace std; ,这个几乎是每个头文件的通用名称空间,其他的c++头文件默认也是这个名称空间,而且还可以这样写:
1 #include <iostream> 2 #include <string> 3 using namespace std;
以后写完一堆头文件后直接在末尾加一句 using namespace std; 就行了。
string的用法:
1 #include <iostream> 2 #include <cstdio> 3 #include <string> 4 using namespace std; 5 6 int main(){ 7 string s; 8 cin >> s; //输入 9 cout << s; //输出 10 11 string s2; 12 s2 = s; //把s里面的内容复制到s2里面 13 14 string s3; 15 s3 = s + s2; //拼接s和s2然后复制到s3里面 16 s = s + s2; //把s2拼接到s末尾 17 18 int len = s.length(); //计算s的长度, 然后赋值到len,功能和strlen()一样,都不算'\0' 19 20 if(s[0] != 'a') s[0] = 'a'; //可以直接像char s[]一样访问和修改 21 22 int cnt = 0; 23 if(s == s2) cnt++; //可以直接比较s和s2是否相等 24 25 return 0; 26 }
vector:不定长数组
1 #include <cstdio> 2 #include <iostream> 3 #include <vector> //相关头文件 4 using namespace std; 5 6 int main(){ 7 //vector(不定长数组)用法介绍 8 vector<int> G; //创建vector 9 G.push_back(5); //加入元素5, 类似于栈 10 G.push_back(3); //加入元素3 11 G.push_back(7); //加入元素7 12 //这时vector里面有元素: 5, 3, 7 13 14 //访问 15 int a; 16 a = G[0]; //a被赋值为vector里面的第一个元素,即a = 5 17 a = G[1]; //a被赋值为vector里面的第二个元素,即a = 3 18 19 //获得vector的大小: G.size() //这里是遍历vector里面的元素 20 for(int i = 0; i < G.size(); i++){ 21 printf("%d\n", G[i]); 22 //这里G.size() == 3, 所以输出G[0], G[1], G[2] 23 } 24 printf("\n"); 25 26 G.clear(); //清空不定长数组G, 相当于不定长数组大小设为0 27 28 //高级用法: vector数组 29 vector<int> g[3]; 30 //这里创建了3个vector, 其中分别是g[0], g[1], g[2] 31 g[1].push_back(4); //向g[1]这个vector加入元素4 32 g[1].push_back(1); //向g[1]这个vector加入元素1 33 34 //访问 35 a = g[1][0]; //a被赋值为g[1]里面的第一个元素,即a = 4 36 a = g[1][1]; //a被赋值为g[1]里面的第二个元素,即a = 1 37 38 for(int i = 0; i < g[1].size(); i++){ 39 printf("%d\n", g[1][i]); 40 //这里g[1].size() == 2, 所以输出g[1][0], g[1][1] 41 } 42 43 return 0; 44 }
map:映射
1 #include <cstdio> 2 #include <iostream> 3 #include <map> 4 #include <string> 5 using namespace std; 6 7 int main(){ 8 //map用法介绍 9 map<string, int> mp; //创建一个map: 从string到1的映射 10 mp["abc"] = 1; //建立从字符串"abc"到整数1的映射 11 string s = "efg"; //创建一个string 12 mp[s] = 5; //建立从字符串"efg"到整数5的映射 13 14 //访问 15 int a; 16 a = mp["abc"]; //这时mp["abc"]的值为1, 也就是a = 1 17 cout << a << endl; 18 a = mp[s]; //这时mp[s]的值为5, 也就是a = 5 19 cout << a << endl; 20 21 //使用char数组 22 char s2[5] = "gsd"; 23 mp[s2] = 9; //建立从字符串"gsd"到整数9的映射 24 cout << mp[s2] << endl; 25 26 mp.clear(); //清空mp里面的元素, 相当于把所有映射都抹去 27 28 //最后注意的是, 虽然map看起来很像hash, 但其内部实现不是hash, 而是一颗树(红黑树) 29 //也就是说, 当进行访问map的操作时, 时间复杂度为O(log m)(m为映射数量), 并不是O(1) 30 31 return 0; 32 }
queue:队列
1 #include <cstdio> 2 #include <iostream> 3 #include <queue> 4 using namespace std; 5 6 int main(){ 7 //queue基本用法 8 queue<int> q; //创建一个先进先出的队列(也就是这个队列只能在尾部加入元素, 头部取出元素, 这个是关键) 9 q.push(1); //加入元素1 10 q.push(2); //加入元素2 11 q.push(3); //加入元素3 12 //这时队列是: 1, 2, 3 13 14 //访问 15 int a; 16 a = q.front(); //这时q.front()的值为1, 所以a = 1, 注意这里只是读取队列首元素, 并没有弹出元素 17 cout << a << endl; 18 a = q.front(); 19 cout << a << endl; 20 21 //弹出 22 q.pop(); //弹出队列的首元素, 也就是变成2, 3 23 a = q.front(); 24 cout << a << endl; 25 26 //判断队列是否为空 27 q.pop(); //弹出队列的首元素, 也就是变成3 28 q.pop(); //弹出队列的首元素, 此时队列为空 29 if(q.empty()) cout << "Yes\n"; //如果队列为空, 则q.empty()为真, 则输出"Yes" 30 if(q.size() == 0) cout << "Yes\n"; //如果队列大小为0, 则输出"Yes" 31 32 return 0; 33 }
sort:排序
1 #include <cstdio> 2 #include <iostream> 3 #include <algorithm> 4 using namespace std; 5 //先从主函数看 6 7 struct node{ 8 int first, second; 9 }; 10 11 bool cmp1(int x, int y){ 12 return x > y; //从大到小排 13 } 14 15 bool cmp2(int x, int y){ 16 return x < y; //从小到大排 17 } 18 19 bool cmp_node(node x, node y){ 20 if(x.first == y.first) return x.second < y.second; 21 else return x.first < y.first; 22 //这里的意思: 优先对结构体的第一个值进行排序, 如果第一个值相等, 就按照第二个值进行排序 23 } 24 25 int main(){ 26 //sort的用法 27 int a[5] = {5,4,3,2,1}; 28 sort(a, a+5); //默认对数组a进行从小到大排序 29 for(int i = 0; i < 5; i++){ 30 cout << a[i] << " "; 31 } 32 cout << endl; 33 34 string s[3] = {"bcd", "abc", "a"}; 35 sort(s, s+3); //默认对字符串进行字典序排序 36 for(int i = 0; i < 3; i++){ 37 cout << s[i] << endl; 38 } 39 cout << endl; 40 41 //自定义比较级(比较函数): 42 sort(a, a+5, cmp1); //按cmp1的比较级排序, 注意这里cmp1后面不能加() 43 for(int i = 0; i < 5; i++){ 44 cout << a[i] << " "; 45 } 46 cout << endl; 47 48 sort(a, a+5, cmp2); //按cmp2的比较级排序 49 for(int i = 0; i < 5; i++){ 50 cout << a[i] << " "; 51 } 52 cout << endl; 53 54 cout << endl; 55 //对结构体进行排序 56 node G[3] = {{5,3}, {5, 2}, {1, 9}}; 57 sort(G, G+3, cmp_node); //按照cmp_node进行排序 58 for(int i = 0; i < 3; i++){ 59 printf("G[%d]: %d %d\n", i, G[i].first, G[i].second); 60 } 61 cout << endl; 62 63 return 0; 64 }
priority_queue:优先队列
1 #include <cstdio> 2 #include <iostream> 3 #include <queue> 4 #include <vector> 5 using namespace std; 6 //从主函数看起 7 8 struct node{ 9 int first, second; 10 }; 11 12 struct cmp1{ //这里比较级是用结构体, 而不是函数 13 bool operator () (int a, int b){ //重载操作, 记住就行 14 return a > b; 15 //小的优先在前面, 因为是用"堆"去实现的, 不清楚堆就直接记住和sort的cmp刚好相反 16 } 17 }; 18 19 struct cmp2{ 20 bool operator () (node a, node b){ 21 if(a.first == b.first) return b.second > b.second; 22 return a.first > b.first; 23 } 24 }; 25 26 int main(){ 27 //priority_queue基本用法 28 priority_queue<int> q; //创建一个优先队列 29 q.push(1); //加入元素1 30 q.push(3); //加入元素3 31 q.push(2); //加入元素2 32 33 if(!q.empty()) printf("YES\n"); //q.empty():判断优先队列是否为空 34 35 int a; 36 while(!q.empty()){ 37 a = q.top(); //这里只是读取队列首元素, 并没有弹出元素 38 printf("%d ", a); 39 q.pop(); //弹出首元素 40 } 41 printf("\n"); 42 //运行上面程序,发现输出为:3, 2, 1, 也就是说, 默认优先队列默认从大到小排列 43 44 priority_queue<int, vector<int>, less<int> > q_less; 45 //创建一个优先级为:从大到小, 排的优先队列 46 47 priority_queue<int, vector<int>, greater<int> > q_great; 48 //创建一个优先级为:从小到大, 排的优先队列 49 50 priority_queue<int, vector<int>, cmp1> q_cmp1; 51 //自定义比较级:cmp1 52 53 priority_queue<node, vector<node>, cmp1> q_cmp1; 54 //自定义比较级:cmp2 55 return 0; 56 }