第一发布 csdn 博客链接
还记得大一上学期含泪用c刷题,那感觉简直爽的不行,后来结识c++发现我错过了一个亿,所以分享一下用c++
刷题所用到的基础知识。
结识算法和OJ就是在大学阶段,当时老师提到OJ,我也是一脸懵,啥是OJ?
后来慢慢开始入门,从校赛第三名,到后来的ACM培训,经历了很多,也学习了很多东西。刷题大约有1000多道了,以后刷题应该暂时不会了,大二就要学习我们大数据专业知识啦。
从c->c++
C语言作为初学者的一门语言,为什么从大一就要开始学呐?
- 相较于其它编程语言(
python
),C
语言是一个比较低级的语言,这样低级的语言,往往能够让我们更加了解计算机。 - 因为比较底层,C语言的执行效率比较高,同样的程序执行效果,肯定C语言执行速度快。
- C语言作为编程界历史最悠久的语言之一,而且至今仍然流行。
- 如果学习过C语言,就能发现学习后面再学习任何高级编程语言都变得轻而易举。
同时,正因为C语言什么都没有,排序,字符串,栈,队列等等,如果刷题的时候,都要自己去实现的话,未免有点浪费时间(前提是你已经很熟悉了,比较基础才是重中之重,知其然,更要知其所以然),所以使用c++刷题,能够提升效率一大截。
c++
能够完全支持c
,打开一个c++
文件,用c
语言的知识写,完全能够运行(关键字不冲突情况下)。c++
的STL
模板库,刷题必备啊!!!栈和队列,集合,向量。用过的都说好。- 字符串处理更加方便,字符数组的方式,每次都不太方便,还有注意
\0
结束符的问题。
学会了这些,走向人生……
C++头文件
如果就是为了刷题,那其实就很简单了。
C语言我们知道头文件是以 #include<stdio.h>
导入头文件,而C++则是用 #include<iostream>
导入头文件。
如果我们想调用C语言头文件怎么办,那就是就是去掉 .h
然后前面加上 c
。
例如,在c++里面引入c语言输入输出的头文件。
#include<cstdio>
这样就能够成功导入了。
#include <cstdio> // 相当于C语⾔⾥⾯的#include <stdio.h>
#include <cstdlib> // 相当于C语⾔⾥⾯的#include <stdib.h>
#include <cctype> // 相当于C语⾔⾥⾯的#include <ctype.h>
#include <cstring> // 相当于C语⾔⾥⾯的#include <string.h>
命名空间
刷题时候都是为了方便,所以才使用 using namespace std;
这样想使用什么直接写就行了。
如果不这样引入,你写的算法可能是这样的 std::
占据注意地方,而且会影响比赛,刷题速度。
std::cout << "hello world" << std::endl;
引入之后:
cout << "hello world" << endl;
看着美观多了。
输入输出
标准输入流(cin
)
预定义的对象 cin
是 iostream 类的一个实例。cin 对象附属到标准输入设备,通常是键盘。cin
是与流提取运算符 >> 结合使用的
#include <iostream>
using namespace std;
int main( )
{
int n;
cin>>n;
}
标准输出流(cout
)
预定义的对象 cout
是 iostream
类的一个实例。cout 对象"连接"到标准输出设备,通常是显示屏。cout
是与流插入运算符 << 结合使用的,
#include <iostream>
using namespace std;
int main( )
{
char str[] = "Hello C++";
cout << "Value of str is : " << str << endl;
}
流插入运算符 << 在一个语句中可以多次使用,如上面实例中所示,endl
用于在行末添加一个换行符。
cin
和 cout
⽐较⽅便,不⽤像C语⾔⾥的scanf
、printf
那样写得那样繁琐,cin >> n;
和scanf("%d", &n);
⼀样(⽽且⽤cin再也不⽤担⼼像scanf
⼀样忘记写取地址符&了)
同样,cout << n;
和printf("%d", n);
此时cout
是向左的两个箭头,注意和cin
区分开来。⽽且不管n
是double
还是int
或者是char
类型,只⽤写cin >> n;
和cout << n;
这样简单的语句就好,不⽤像C语⾔中需要根据n的类型对应地写%lf、%d、%c
这样麻烦。
字符串
c++
用到最多的就是字符串了,跟之前的字符数组类似,但是字符数组,操作起来相当麻烦,显然使用c++
的字符串会方便的多。
定义一个字符串,导入库 <string>
string s = "hello world";//赋值
cout<<s<<endl;
s = "world";
cout<<s<<endl;
输出为
hello world
world
字符串拼接(可以直接相加)
string s1 = "hello";
string s2 = " world";
string s = s1 + s2;//拼接直接使用 + 号
读入字符串
string s; // 定义⼀个空字符串s
cin>>s;//不包括空格
getline(cin, s); // 读取⼀整⾏的字符串,包括空格
字符串长度(两种方法等价)
int len = s.size();//字符串s的⻓度
int len = s.length();//字符串s的⻓度
查找字符串t是否是s的子串
如果t是s的子串则返回首次匹配的位置,否则返回 string::npos 或 -1
s.find(t);
begin
和 end
方法
begin()函数返回一个迭代器,指向字符串的第一个元素.返回值是字符串的首地址,取值为*
end()函数返回一个迭代器,指向字符串的最后一个元素.返回值是字符串的首地址,取值为*
string s1 = "hello";
string s2 = " world";
s1.append(s2);
cout<<*s1.begin()<<endl;
cout<<*s1.end()<<endl;
反转字符串
string s = "hello world";
reverse(s.begin(), s.end());
cout<<s<<endl;
//结果
dlrow olleh
截取某个字符串中的⼦串 substr
这个函数在处理字符串的题目很常用,当然,用这个方法很多时候会 TLE
string s = "hello world";
string s1 = s.substr(6);//下标6开始到结束
string s2 = s.substr(0, 11);//下标0开始,截取11个字符
cout<<s1<<endl;
cout<<s2<<endl;
//结果
world
hello world
栈
使用标准库的栈和队列时,先包含相关的头文件
stack<int> s;
s.empty() 如果栈为空返回true,否则返回false
s.size() 返回栈中元素的个数
s.pop() 删除栈顶元素但不返回其值
s.top() 返回栈顶的元素,但不删除该元素
s.push() 在栈顶压入新元素
#include <iostream>
#include <stack>
using namespace std;
int main() {
stack<int> s; // 定义⼀个空栈s
for (int i = 0; i < 6; i++) {
s.push(i); // 将元素i压⼊栈s中
}
cout << s.top() << endl; // 访问s的栈顶元素
cout << s.size() << endl; // 输出s的元素个数
s.pop(); // 移除栈顶元素
return 0;
}
队列
q.push(x):将x元素接到队列的末端;
q.pop() 弹出队列的第一个元素,并不会返回元素的值;
q.front()访问队首元
q.back()访问队尾元素
q.size()访问队中的元素个数
优先队列
优先队列是计算机科学中的一类抽象数据类型。优先队列中的每个元素都有各自的优先级,优先级最高的元素最先得到服务;优先级相同的元素按照其在优先队列中的顺序得到服务。优先队列往往用堆来实现。
priority_queue<node> q;
q.empty() 如果队列为空,则返回true,否则返回false
q.size() 返回队列中元素的个数
q.pop() 删除队首元素,但不返回其值
q.top() 返回具有最高优先级的元素值,但不删除该元素
q.push() 在基于优先级的适当位置插入新元素
集合
set
是集合,⼀个set
⾥⾯的各元素是各不相同的,⽽且set
会按照元素进⾏从⼩到⼤排序以下是set
的常⽤⽤法:
#include <iostream>
#include <set>
using namespace std;
int main() {
set<int> s;
s.insert(2);//向集合添加元素
s.insert(3);//向集合添加元素
cout << *(s.begin()) << endl; //输出第一个元素
for (int i = 0; i < 10; i++) {//插入0 - 9
s.insert(i);
}
for (set<int>::iterator it = s.begin(); it != s.end(); it++) {
cout << *it << " ";//集合的遍历,it是一个迭代的指针
}
cout << endl << (s.find(2) != s.end()) << endl;//查找,元素
s.erase(3);//删除元素
cout << (s.find(3) != s.end()) << endl;
return 0;
}
map/字典/映射
map是键值对,⽐如⼀个⼈身份证对应⼀个人的信息,就可以定义⼀个字符串类型的身份证字符串为“键”,个人信息为“值”,如map<string, int="" style="font-size: inherit; color: inherit; line-height: inherit; margin: 0px; padding: 0px;"> m;map会⾃动将所有的键值对按照键从⼩到⼤排序。
类似于python的字典,键值唯一。
map使⽤时的头⽂件#include 以下是map中常⽤的⽅法:
#include <iostream>
#include <map>
#include <string>
using namespace std;
int main() {
map<string, string> m;
m["hello"] = "world"; // 存储键为 "hello" 值为 "world"的键值对
cout << m["hello"] << endl; // 访问map中key为"hello"的value,
cout << m["world"] << endl;// 如果key不存在,则返回0或空
m["world"] = "test"; // 将"world"键对应的值修改为3
m["key"] = "value"; // 设置键为 "key" 值为"value" 的键值对
//迭代器遍历,输出map中所有的元素,键it->first获取,值it->second获取
for (map<string, string>::iterator it = m.begin(); it != m.end(); it++) {
cout << it->first << " " << it->second << endl;
}
cout << m.begin()->first << " " << m.begin()->second << endl;
// 访问map的第一个元素,输出它的键和值
cout << m.rbegin()->first << " " << m.rbegin()->second << endl;
// 访问map的最后一个元素,输出它的键和值
cout << m.size() << endl;
// 输出map的元素个数
return 0;
}
向量
在c++中,vector是一个十分有用的*容器*。
作用:它能够像容器一样存放各种类型的对象,简单地说,vector是一个能够存放任意类型的动态数组,能够增加和压缩数据。
新建一个向量存储int
类型
vector<int>test; // 定义的时候不指定vector的⼤⼩
vector<int>test2(6); // 定义的时候指定vector的⼤⼩,默认test2⾥⾯元素都是0
vector<int>test3(6, 3); // 定义的时候指定vector的⼤⼩,默认test3⾥⾯元素都是3
尾部添加两个元素,0的位置存储5, 1 的位置存储8
test.push_back(5);
test.push_back(8);
插入元素 insert
test.insert(test.begin()+i,value);//在第i+1个元素前面插入value;
删除元素
test.erase(test.begin() + 5);//删除第6个元素
清空向量
test.clear();//clear
获取向量的大小
test.size();
获取起始地址或结束地址
test.begin();//起始地址
test.end();//结束地址
遍历向量
for (vector<int>test::iterator it = m.begin(); it != m.end(); it++) {
cout << *it << endl;
}
反转元素,逆序
reverse(test.begin(),test.end());//反转
使用sort
排序,可以自定义排序规则
sort(test.begin(),test.end());