212
社区成员
在使用C语言的时候大家可能对一些写法可能非常的难受,觉得不方便
那么我们快速的学习一下C++,使你写代码的效率提高100倍(写数据结构和算法的时候)
#include<bits/stdc++.h> //万能头文件
using namespace std; //和命名空间有关,用不用万能头文件都要写
#include<iostream> //输入流和输出流,也是基础头文件
using namespace std;
//列举一下等等会讲的精通就能在下个学期的题目里乱杀
//但是不推荐下个学期写题直接用这些工具
//学习完C语言的基础写法再这样写比较好
//下面这些头文件都可以用万能头文件替代
#include<algorithm> //算法头文件
#include<vector> //方便操作的数组
#inlcude<set> //自动排序且无重复元素的容器
#include<map> //自动排序且无重复元素的键值对容器
#include<stack> //堆栈
#include<queue> //队列
#include<string> //字符串数组
在C++中,大部分(应该是全部)的C语言语法都是可以用的
代码转换介绍:
//输入和输出
int x;
char c;
//C语言写法(C++也可以这么写)
scanf("%d %c",&x,&c);
prinf("%d %c",x,c);
//C++写法
cin >> x >> c;
cout << x << " " << c;
//虽然C++这个好写,但是效率比较低,耗时更久,但是影响不大,而且可以用别的代码提高,这里就不多说了
//auto定义实现for循环
for(auto i : 容器)
//这里的容器可以是前面提到的所有
//这里的i是个迭代器,需要用*i来获取值
代码:
//vector<数据类型> v;
//例如
vector<int> v;
vecotr<struct p> v;
vector<string> v;
vector<vector<int>> v; //二维数组
vector<set<int>> v;
vector<vector<vector<int>>> v; //三维数组
//使用(int类型举例)
vector<int> v;
int x;
//存入数据
v.push_back(x);
//首元素
v.begin();
//尾元素后面的一个元素
v.end(); //其实就是 NULL
//删除数据 v.erase(迭代器)
v.erase(v.begin());
//for循环的两种写法,各自都有自己的使用领域
//1 --只有vector可以这么遍历,其他的所有容器都不可以
for(int i=0;i<v.size();i++){
v[i] = i;
}
//2
for(auto i:v)
*i = 0;
//其他的常用方法
v.resize(100); //一般用于扩容
vector其实就是数组,没有什么特别的地方
作用:代替数组而存在吧,但是有时候还是数组更方便(用数组:已经知道数据的大小,比如djk的最短路径写法)
应用场景:数组开的空间是有上限的,但是vector只要你不限制内存就可以无限制的开
作用:排序读入的数据,且不插入重复的数据
这个容器我们直接用一个例题来讲解:
题目:输入:无限个随机数,输出:每读入10000个数据,将数据排序且删除重复的数据,并且输出后重新计数
例如:输入:9 8 4 6 7 1 3 8 9 4 5 输出:1 3 4 5 6 7 8 9
#include<iostream>
#include<set>
using namespace std;
int main(){
set<int> s;
int cnt = 0;
while(true){
int x;
cin >> x;
cnt++;
s.insert(x); //插入数据 删除(用的很少)应该还是erase 要用的话直接百度查C++ set
if(cnt == 10000){
cnt = 0;
for(auto i:s) cout << *i << " ";
cout << endl;
s.clear(); //清空set容器的数据
}
}
}
通过这一个例子大家应该就能理解set容器的作用,当然他排序和删除重复元素的功能是需要耗时,效率不一定高,他的底层代码是红黑树(大二应该会做一定的了解,但是不会深入)
set容器只需要会创建,且会插入,会清空,会遍历(这个容器只能用迭代器遍历)即可(最多再学一个find()函数,用于查找某个元素是否在集合中)
作用:在set的基础上变成存储的是键值对
一样也是列举个题目举例:
题目:输入:无限的随机数,输出:每读入10000个数据,按顺序输出数据且输出每个数据出现的次数,不清空
代码:
#include <iostream>
#include <map>
using namespace std;
int main() {
int num, cnt = 0;
map<int, int> mp;
while (true) {
cin >> num
mp[num]++; //读入数据
cnt++;
if (cnt % 10000 == 0) {
for (auto it : mp) {
cout << it.first << ": " << it.second << endl;
}
//清空也是clear,但是本题不清空
//mp.clear(); // 清空 map,准备下一组数据统计
}
}
}
map存储的结构是键值对,举个例子:
我们普通的数据都是
a[1] = 2; //这么写数据至少是a[2]
//a[0] 是一定可以访问的
这么写的,而map<int,int>创建的数组
a[1] = 2; //这么写数据至少是a[2]
//a[0] 是不一定可以访问的,除非a[0]也被定义过,否则会段错误
所以map不是一个连续的数据,他只会存储你给的key,所以map还有下面的几种常用写法
map<string,int> mp;
map<string,string> mp;
map<int,string> mp;
mp["a"] = 1; //就变得可以实现了(下个学期你们写数构就会碰见这么一题)
介绍:堆栈顾名思义就是,一个可以塞东西的容器,先塞进去的数据就不好拿出来,只能拿出来刚塞进去的东西
学长奇怪的比喻:比如一个单向的山洞,且宽度只有一个人的宽度,一个人走进山洞,后面又进来一个人,那么先进去的人只能等后进来的人走了才能出去
代码:
stack<int> s;
//输入:1 2 3 4 5 6
//输出:6 5 4 3 2 1
int x;
while(cin >> x){
s.push(x); //把数据加入容器
}
while(s.empty()){ //判断s中是否有数据
cout << s.top() << " "; //最晚进入容器的数据
s.pop(); //删除最晚进入容器的数据
}
作用:多用于写dfs(一个你们下个学期会学习的算法,且这个算法会贯彻你们的算法之路)
介绍:队列顾名思义就是,一个队伍,前进去的可以先出来,后进去的晚出来
学长奇怪的比喻:大家去食堂打饭,先排队的人可以先打到饭,后排队的人只能排在队伍的最后面,最晚打饭
代码:
queue<int> q;
输入:1 2 3 4 5 6
输出:1 2 3 4 5 6
int x;
while(cin >> x){
q.push(x); //插入元素
}
while(!q.empty()){
cout << q.front() << endl; //队列的第一个元素
q.pop(); //删除最早进入队列的元素
}
q.back() //最晚进入的元素,虽然可以访问,但是删不掉
作用:用于写bfs(bfs和dfs是比较类似的算法,有的题目是可以互相转换的,也是比较重要的)
介绍:字符串,类似于char[],但是比char[]好用100倍
所以这个也是这篇博客的重中之重
不多废话,直接讲代码
两种用途比较广的写法,且效果不一样
string s;
//输入:hello world!
//读入单个字符串(也可以是数字)
cin >> s;
cout << s;
//输出:hello
//读入一行数据
getline(cin,s); //cin是固定的,s是存储的容器
cout << s;
//输出:hello world!
//还有!!!!
cout << s[1]; //string本质是数组,这么写是可行的
其实就是ASCII码的比较
1. 字符串a是b的子串,那么b比较大
例如:
"abc" < "abcd"
2. 如果字符串前 i 个字符相同 ,那么第 i+1 个字符较大的那个字符串更大,和 i+1 后的字符就没有任何关系了
例如:
"abcd" < "abda"
为什么要单独讲一下这个呢,就是因为 atoi() 这个函数只能用在 char[] 上
atoi():将字符串转换成数字
string s;
atoi(s.c_str);
string s1 = "hello"
string s2 = " world!"
s1+=s2;
cout << s1; //hello world!
s.substr() //没参数就是整个s串
s.substr(下标) //拷贝s串 下标 开始的整个串
s.substr(下标, 长度) //拷贝s串 下标 开始的长度为 长度 的串
//例子
string s ("hello");
string s1 = s.substr(); //hello
string s2 = s.substr(1); //ello
string s3 = s.substr(2,2) //ll
最效率的方法:KMP算法,但是代码很长(50行左右)
最简单的方法(且能过老师布置的大(bai)部(fen)分(bai)题目):
string s1 = "ello w";
string s2 = "hello world!"
if(s2.find(s1) != -1)
cout << "s1是s2的子串" << endl;
else
cout << "s1不是s2的子串" << endl;
string是不是比char[]好用太多了!!!!
这些还不是string全部的函数,还有其他的函数大家可以自己去查(百度:C++ string),这篇博客就讲一下比较常用的函数,比较师父领进门,修行靠个人嘛
这里主要将一个sort()函数,其他就不写了,因为用的不多
//其实不知道是不是这么拼,反正差不多
#include<algorithm>
#include<vetor>
struct p{
int x;
int y;
};
vetor<struct p> v;
bool cmp(struct p p1,struct p p2){
return p1.x+p1.y > p2.x+p2.y;
//x+y比较大的在前面
}
int main(){
//获取一下数据
//......
//假设数据
//x: 1 3 5 7 2 4
//y: 9 8 8 2 3 4
//t: 10 11 13 9 5 8 //没有这个数据,只是算一下上面的总和
//排序
sort(v.begin(),v.end(),cmp);
for(auto i: v) cout << i->x << " " << i->y << endl; //endl是换行
//输出结果
//5 8
//3 8
//1 9
//7 2
//4 4
//2 3
}
以上就是比较常用的C++语法,掌握这些就能算是基本入门了,能看懂大部分的C++代码(不懂的问ChatGPT),更多的语法可以刷算法题看题解的时候慢慢领悟(就像高中的时候写数理化的时候一样,多写让思维跳跃起来就可以啦),其实也就是大家经常能听见的那句经典(菜就多练,以前是以前,现在是现在),算法前路漫漫,写完C语言的2840,下个学期还要数据结构3000多分,加油!!!!