我是主写python的,但是感觉算法上想精进的话,还是得用c++写,所以笔记主要记录的是c++与python不太一样的地方,听的是y总的算法基础课,结合y总的讲义,白框里面是自己的理解,大家取精华,去糟粕
基本格式
头文件
include <iostream> /主要包含cin和cout基本输入输出流
include <cstdio> /主要包含scanf和printf输入输出函数
数据规模大时,scanf和printf的速度远比cin和cout速度快,但我个人做了一部分题后,还没出现这种原因导致超时,所以按照自己的习惯用就行
(我个人是,如果输出有格式规定,例如浮点数之类的,用printf,剩下我习惯于用cout,因为写起来较快 )
using namespace std;
这个语句的作用感兴趣可以自己查一下,有的编译器默认加上了,但我习惯自己写上
万能头文件,包含所有c++可能用到的库函数
#include <bits/stdc++.h>
主函数
基本格式
!注意变量要提前定义
#include <iostream>
#include <cstdio>
using namespace std;
int main()
{
int n;
cin >> n; /输入
cout << n << endl; /输出
return 0;
}
循环
eg:打印1-100以内的质数
数组
初始化数组
数组操作
访问数组的方式与python一致
/求元素个数
cout << sizeof(arr) / sizeof(arr[0]) << endl;
多维数组
字符数组
字符串就是字符数组加上结束符’\0’。
可以使用字符串来初始化字符数组,但此时要注意,每个字符串结尾会暗含一个’\0’字符,因此字符数组的长度至少要比字符串的长度多1!
字符数组的常用操作
下面几个函数需要引入头文件:
#include <string.h>
(1) strlen(str),求字符串的长度
(2) strcmp(a, b),比较两个字符串的大小,a < b 返回-1,a == b 返回0,a > b返回1。这里的比较方式是字典序!
(3) strcpy(a, b),将字符串b复制给从a开始的字符数组。
字符串类型 string
可变长的字符序列,比字符数组更加好用。需要引入头文件:
#include < string>
输出整个字符串
#include < iostream>
#include < string>
using namespace std;
int main()
{
string s1;
cin >> s1;
printf("%s", s1.c_str());
return 0;
}
字符串构造 赋值+拼接
#include <string>
void text2()
{
string s1;
s1 = "hello world";
s1 += "C++"
const char * str = "hello world"; /const 限定符,它把一个对象转换成一个常量
string s2(str);
string s3(s2);
string s4(5,'a'); /aaaaa
}
其他操作
1)查找
string str1 = "abcdef";
int a = str1.find("def");
2)替换
string str2 = "aaabbb"
str2.replace(3,3,"aaa")
3)比较
str1.compare(str2) == 0相等
>0 str1大
<0 str2大
4)字符存取
string str1 = "hello";
for (int i = 0; i < str.size(); i++)
{
cout << str[i] << " ";
cout << str.at(i) << " ";
}
cout << endl;
5)字符串修改
str[0] = 'a';
6)插入,删除
string str = "hello";
str.insert(1,"zzz");
sr.erase(1,3) //开始位置,几个
7)求字串
string str = "abcdefg";
string s = str.substr(1,3);
8)count
count(s.begin(),s.end(),'a');
C++ STL
STL是提高C++编写效率的一个利器。——y总
1)vector容器
构造
void text3()
{
vector<int>v1; /默认构造,无参构造
for (int i = 0; i < 10; i++)
{
v1.push_back(i)
}
printVector(v1);
/通过区间方式进行构造
vector<int>v2(v1.begin(),v1.end());
/n个elem方式构造
vector<int>v3(10,100);
/拷贝构造
vector<int>v3(v4);
}
遍历
#include <vector>
#include <algorithm> /标准算法头文件
void myPrint(int val)
{
cout << val << endl;
}
void text1()
{
vector<int> v;
/向容器中插入数据
v.push_back(10);
v.push_back(20);
/通过迭代器访问容器中的数据
vector<int>::iterator itBegin = v.begin(); /起始迭代器,指向容器中第一个元素
vector<int>::iterator itEnd = v.end(); //结束迭代器,指向容器中最后一元素的下一个位置
/遍历方式一
while (itBegin != itEnd)
{
cout << *itBegin << endl;
itBegin++;
}
/遍历方式二
for(vector<int>::iterator it = v.begin(); it != v.end();it++)
{
cout << *it << endl;
}
/遍历方式三
for_each(v.begin(), v.end(), myPrint);
}
其他操作函数
size()/empty()
size函数返回vector的实际长度(包含的元素个数),empty函数返回一个bool类型,表明vector是否为空。二者的时间复杂度都是O(1)。
所有的STL容器都支持这两个方法,含义也相同,之后我们就不再重复给出。
begin()/end()
begin函数返回指向vector中第一个元素的迭代器。例如a是一个非空的vector,则*a.begin()与a[0]的作用相同。
front()/back()
front函数返回vector的第一个元素,等价于*a.begin() 和 a[0]。
back函数返回vector的最后一个元素,等价于*==a.end() 和 a[a.size() – 1]。
push_back() 和 pop_back()
a.push_back(x) 把元素x插入到vector a的尾部。
b.pop_back() 删除vector a的最后一个元素。
sort()排序
#include <algorithm>
sort(d.begin(), d.end());
/倒序
sort(d.rbegin(),d.rend());
用swap收缩内存
vector<int>(v).swap(v);
预留空间
v.reserver(10000)
2)set容器
特点,元素插入时自动排序,不容许有重复值
不容许有重复值是c++和python的共同点,但python的set是无序的,而c++是有序的
头文件set主要包括set和multiset两个容器,分别是“有序集合”和“有序多重集合”,即前者的元素不能重复,而后者可以包含若干个相等的元素。set和multiset的内部实现是一棵红黑树,它们支持的函数基本相同。
#include<set>
set<int>s;
/插入数据
s.insert(10);
s.insert(20);
/拷贝构造
set<int>s2(s1);
/判断为空
if (s.empty())
/大小
s.size()
insert(elem) //插入
clear() /清除所有元素
erase(pos) / 删除pos迭代器所指的元素,返回下一个元素的迭代器 s.begin() s.end()
erase(begin,end) /删除区间所有元素,返回下一个元素的迭代器
erase(elem) /删除容器中值为elem的元素
find() //不存在返回set.end()
count() //统计个数0/1
lower_bound()/upper_bound()
这两个函数的用法与find类似,但查找的条件略有不同,时间复杂度为 O(logn)。
s.lower_bound(x) 查找大于等于x的元素中最小的一个,并返回指向该元素的迭代器。
s.upper_bound(x) 查找大于x的元素中最小的一个,并返回指向该元素的迭代器。
/利用仿函数指定set容器的排序规则
class MyCompare
{
public:
bool operator()(int v1, int v2) const
{
return v1 > v2;
}
}
set<int,MyCompare>s2;
deque容器
双端队列deque是一个支持在两端高效插入或删除元素的连续线性存储空间。它就像是vector和queue的结合。与vector相比,deque在头部增删元素仅需要O(1)的时间;与queue相比,deque像数组一样支持随机访问。
[] 随机访问
begin/end,返回deque的头/尾迭代器
front/back 队头/队尾元素
push_back 从队尾入队
push_front 从队头入队
pop_back 从队尾出队
pop_front 从队头出队
clear 清空队列
map容器
map容器是一个键值对key-value的映射,其内部实现是一棵以key为关键码的红黑树。Map的key和value可以是任意类型。
声明
map<key_type, value_type> name;
例如:
map<long, long, bool> vis;
map<string, int> hash;
map<pair<int, int>, vector<int>> test;
size()/empty()/clear()/begin()/end()均与set类似。
insert()/erase()
与set类似,但其参数均是pair<key_type, value_type>。
find()
h.find(x) 在变量名为h的map中查找key为x的二元组。
[]操作符
h[key] 返回key映射的value的引用,时间复杂度为O(logn)。
[]操作符是map最吸引人的地方。我们可以很方便地通过h[key]来得到key对应的value,还可以对h[key]进行赋值操作,改变key对应的value。
小知识点补充
#include <cmath >
包含一些常用的数学函数
1、ceil(x) /向上取整
2、floor(x) /向下取整
3、fabs(x) /x的绝对值
4、sqrt(x) /x的平方根
5、pow(x,y) /x的y次幂
浮点数的定义和输入输出
double r;
scanf("%lf", &r);
printf("%.4lf", r * r); /四位小数;
/%8.3f, 表示这个浮点数的最小宽度为8,保留3位小数,当宽度不足时在前面补空格
/%-8.3f,表示最小宽度为8,保留3位小数,当宽度不足时在后面补上空格
/%08.3f, 表示最小宽度为8,保留3位小数,当宽度不足时在前面补上0
生成随机数
#include <stdlib.h>
#include <ctime>
srand((unsigned int) time(NULL)); /添加随机数种子,防止每次随机数一样
int num = rand()%100 /生成0 ~ 99随机数