再也不用c刷题了!!——c++刷题必备

致读者: 博主是一名数据科学与大数据专业大二的学生,真正的一个互联网萌新,写博客一方面是为了记录自己的学习历程,一方面是希望能够帮助到很多和自己一样处于困惑的读者。由于水平有限,博客中难免会有一些错误,有纰漏之处恳请各位大佬不吝赐教!之后会写大数据专业的文章哦。尽管当前水平可能不及各位大佬,但我会尽我自己所能,做到最好☺。——天地有正气,杂然赋流形。下则为河岳,上则为日星。

第一发布 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

预定义的对象 ciniostream 类的一个实例。cin 对象附属到标准输入设备,通常是键盘。cin 是与流提取运算符 >> 结合使用的

#include <iostream>
using namespace std;
int main( )
{
    int n;
    cin>>n;
}

标准输出流(cout

预定义的对象 coutiostream 类的一个实例。cout 对象”连接”到标准输出设备,通常是显示屏。cout 是与流插入运算符 << 结合使用的,

#include <iostream>
using namespace std;
int main( )
{
   char str[] = "Hello C++";
   cout << "Value of str is : " << str << endl;
}

流插入运算符 << 在一个语句中可以多次使用,如上面实例中所示,endl 用于在行末添加一个换行符。

cincout ⽐较⽅便,不⽤像C语⾔⾥的scanfprintf那样写得那样繁琐,cin >> n;scanf("%d", &n);⼀样(⽽且⽤cin再也不⽤担⼼像scanf⼀样忘记写取地址符&了)
同样,cout << n;printf("%d", n);此时cout是向左的两个箭头,注意和cin区分开来。⽽且不管ndouble还是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);

beginend 方法

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(011);//下标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<stringstring> 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<stringstring>::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(63); // 定义的时候指定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());