算法笔记(C++)

时间:2022-02-16 11:31:46

一、基础篇

C++标准模板库(STL)

1.vector

可以理解为“变长数组”

#include <vector>
vector<typename> name;
vector<vector<int> > name; //两个维都可变长的二维数组 >>之间要加空格
vector<typename> Arrayname[arraySize]; //Arrayname[0]~Arrayname[arraySize-1]中每一个都是一个vector容器
  • .size() 获取vector中元素的个数,返回unsigned类型

  • .clear()

  • .push_back(x) 在vector后面添加一个元素x

  • .pop_back() 删除vector的尾元素

  • .insert(it, x) 向vector的任意迭代器it处插入一个元素x

  • 通过下标访问: vi[0] ~ vi[vi.size()-1]

  • 通过迭代器访问

for(vector<int>::iterator it = vi.begin(); it!=vi.end(); it++){
printf("%d ", *it);
}
//end()是尾元素地址的下一个地址
  • .erase():删除一个元素、删除一个区间内的所有元素

vi.erase(it);  //删除迭代器为it处的元素
vi.erase(a, b); //删除[a,b)内所有元素

2.set

集合,是一个内部自动有序且不含重复元素的容器

#include <set>
set<typename> name;
set<typename> Arrayname[arraySize]; //Arrayname[0]~Arrayname[arraySize-1]中每一个都是一个set容器
//遍历
for(set<int>::iterator it = name.begin(); it!=name.end(); it++){
//骚操作
if(name.find(*it) != name.end()){//怎么判断查找到
}
}
  • set容器内的元素只能通过迭代器访问

  • .size()

  • .clear()

  • .insert(x)将x插入set容器中,并自动递增排序和去重

  • .find(value) 返回set中对应值为value的迭代器

  • .erase():删除单个元素、删除一个区间内的所有元素

3.string

#include <string>
string str;
string str = "abcd";
//如果要读入和输出整个字符串,则只能用 cin 和 cout
  • 可以通过迭代器 或 下标访问

  • operator+=

str3 = str1 + str2;
str1 += str2;
  • compare operator 比较规则是字典序

    ==、!=、<、<=、>、>=

  • .length() / .size() 返回string的长度

string str = "abcxyz";
printf("%d %d\n", str.length(), str.size());
//输出 6 6
  • .insert()

str.insert(pos, str2); //在pos号位置插入字符串str2,str2处直接"..."也行
string str = "abcxyz", str2 = "opq";
str.insert(str.begin()+, str2.begin(), str2.end());//在str的3号位(即c和x之间)插入str2
  • .erase() //str.erase(pos, length) pos为开始删除位置,length为删除的字符个数

  • .clear()

  • .substr(pos, len) 返回从pos号位开始、长度为len的子串

  • str.find(str2) 当str2是str的子串时,返回其在str中第一次出现的位置;若不是,那么返回string::npos(-1或4294967295)

  • str.replace(pos, len, str2) 把str从pos号位开始、长度为len的子串替换为str2

    str.replace(it1, it2, str2) 把迭代器[it1,it2)范围的子串替换为str2

4.map

映射,键值对,键唯一;

map会以键从小到大的顺序自动排序

#include <map>
map<typename1, typename2> mp;
map<string, int> mp; //如果是字符串到整型的映射,必须使用string而不能使用char数组
map<string, vector<int> > mp; //map的键、值也可以是STL容器
  • map可以通过下标(mp['c']) 或 迭代器访问

map<typename1, typename2>::iterator it;
//it->first访问键 it->second访问值
  • map<char, int>::iterator it = mp.find('b'); 返回的是被查找元素的位置,没有则返回map.end()

  • mp.count('b') 返回的是被查找元素的个数,如果有,返回1(因为键唯一);否则返回0

  • .erase()

  • .size()

  • .clear()

5.queue

队列,先进先出的容器

#include <queue>
queue<typename> name;
  • .front()访问队首元素、.back()访问队尾元素

  • .push(x) 将x进行入队

  • .pop() 令队首元素出队

  • .empty() 检查queue是否为空

  • .size()

6.stack

栈,后进先出的容器

#include <stack>
stack<typename> name;
  • .push(x) 将x入栈

  • .top() 获得栈顶元素

  • .pop() 弹出栈顶元素

  • .empty()

  • .size()

7.priority_queue

优先队列,其底层是用堆(大顶堆)来实现的,队首元素一定是当前队列中优先级最高的那个

#include <queue>
priority_queue<typename> name;
  • 优先队列没有队列中的front()函数 与 back()函数,只能通过 .top() 函数访问队首元素

  • .push(x)

  • .pop()

  • .empty()

  • .size()

priority_queue优先级设置:

priority_queue<int, vector<int>, less<int> > q;
//第二个参数 vector<int>用来承载底层数据结构堆(heap)的容器,若第一个参数是double或char型,此处只需填写vector<double> 或 vector<char>
//less<int> 表示数字越大的优先级越大
//greater<int> 表示数字小的优先级大

常用函数或注意点

1.reverse函数

//使用reverse将元素翻转
#include <algorithm>
vector<int> vec = {,,,,};
reverse(vec.begin(),vec.end()); //将元素翻转,即逆序排列 5, 4, 3 ,2 ,1
string str="C++REVERSE";
reverse(str.begin(),str.end());//str结果为ESREVER++C

2.转义字符

/*
\n代表换行
\0代表空字符NULL,其ASCII码为0,请注意\0不是空格

3.强制类型转换

(类型名)变量名;

4.符号常量和const常量

#define pi = 3.14   //注意末尾不加分号
const double pi = 3.14;

5.小数建议使用double类型,以保证精确度

6.<cmath>头文件中常用的math函数

#include <cmath>
fabs(double x) //对double类型变量取绝对值
floor(double x) //对double类型变量向下取整
ceil(double x) //对double类型变量向上取整
pow(double r, double p) //返回r的p次方
sqrt(double x) //求算术平方根
log(double x) //返回double变量的以自然对数为底的对数 ****************
//C中没有任意底数求对数的函数, logab = logeb/logea
sin(double x) cos(double x) tan(double x)
asin(double x) acos(double x) atan(double x)
round(double x) //将double变量四舍五入,返回类型也是double型,需进行取整

7.初始化 memset函数 和 fill函数

bool isExist[maxn] = {false};
memset(isExist, false, sizeof(isExist)); //memset函数在 <cstring>里
//因为memset函数按照字节填充,所以一般memset只能用来填充char型数组,(因为只有char型占一个字节)如果填充int型数组,除了0和-1,其他的不能。因为只有00000000 = 0,-1同理,如果我们把每一位都填充“1”,会导致变成填充入“11111111”
//推荐
include <algorithm> //在 <algorithm>里面
int arr[maxn];
fill(arr, arr+maxn, 要填入的内容);

8.结构体(struct)内不能定义自己本身,但可以定义自身类型的指针变量

9.圆周率 π

const double Pi = acos(-1.0);

10.string.h头文件

strlen(字符数组)   //得到字符数组第一个\0前得字符的个数
strcmp(str1, str2) //比较 str1==str2,返回0;str1>str2,返回正数;str1<str2,返回负数
strcpy(str1, str2) //复制
strcat(str1, str2) //拼接

11.printf输出特殊符号和常用的输出形式

//输出 %  或  \
printf("%%");
printf("\\");
// %md 可以使不足m位的int型变量以m位进行右对齐输出,其中高位用空格补齐;如果变量本身超过m位,则保持原样
// %0md 较上不同是变量不足m位时,0补位
// %.mf 可以让浮点数保留m位小数输出

12.scanf

scanf的 %c 格式可以读入换行符和空格,因此需要在每行输入前把上一行的换行符接收,使用getchar()

除了 %c 外,scanf对其他格式符(如%d %s)的输入是以空格、换行等为结束判断标志的,

因此除非使用%c把空格字符读入,其他情况都会自动跳过空格。

13.cin 和 cout

//以下两者常用于输入一行数据
char str[]; //char数组
cin.getline(str, );
string str; //string容器
getline(cin, str);

14.getchar() putchar() gets() puts()

getchar可以识别换行符,用getchar输入字符串最后勿忘加 '\0',否则输出会出现乱码

gets识别换行符\n作为输入结束

puts自带换行符

c = getchar();
putchar(c);
//puts(s) == printf("%s\n", s);
gets(s); //接收输入的整个字符串直到回车为止
scanf("%s", &s);//如果输入了空格会认为输入字符串结束, 空格后的字符将作为下一个输入项处理

15.sscanf sprintf (不易想起)

sscanf(str, "%d", &n)   //把字符数组str中的内容以 %d 的格式写到 int n 中
sprintf(str, "%d", n) //把 n以 %d 的格式写到 str 字符数组中去

16.long long 为64位 即2^64 ,两个int相乘最大数据范围可达 long long

17.小数的四舍五入

printf("%.2lf", final);
//C++的输出不提供四舍五入功能,若要四舍五入,上述为例:
printf("%.2lf", final+0.005);

18.int To string

string str = to_string(int val); //参数可为其他类型,如 long、float、double等

string To int 、double、long

#include <stdlib.h>
char *str = "12345.67";
int n = atoi(str); //字符串转换为整数(atoi)、长整数(atol)
double d = strtod(str,NULL); //字符串转换为浮点数,与atof()使用结果相同

string To char

string str = "";
char *p = str.c_str();
int x = atoi(p);
str = to_string(x);

19.大小写转换

//C语言
char c;
toupper(c);//转大写
tolower(c);//转小写
//C++
string str = "Asd";
str[] += ; //A转小写
str[] -= ; //s转大写

20.N不会被除自己以外的大于根号N的整数整除(减少运算复杂度)

21.起始输入的个数不确定的情况

//输入情况如下:7 5 31 5 88 67 88 17  个数不确定
//进行字符串转数字操作
string str;
getline(cin, str); //接收一行数据
for(int i=; i<str.length(); i++){ //数据处理
int j;
for(j=i; j<str.length(); j++){
if(str[j] == ' ') break;
}
int x = ;
for(int k=i; k<j; k++){
x = x * + str[k] - '';
}
temp[num] = x;
num++;
i = j;
}
//输入情况如下:7 5 31 5 88 67 88 17  个数不确定
//进行字符串转数字操作
string str;
getline(cin, str); //接收一行数据
for(int i=; i<str.length(); i++){ //数据处理
int j;
for(j=i; j<str.length(); j++){
if(str[j] == ' ') break;
}
int x = ;
for(int k=i; k<j; k++){
x = x * + str[k] - '';
}
temp[num] = x;
num++;
i = j;
}
//输入情况如下:7 5 31 5 88 67 88 17  个数不确定
//进行字符串转数字操作
string str;
getline(cin, str); //接收一行数据
for(int i=; i<str.length(); i++){ //数据处理
int j;
for(j=i; j<str.length(); j++){
if(str[j] == ' ') break;
}
int x = ;
for(int k=i; k<j; k++){
x = x * + str[k] - '';
}
temp[num] = x;
num++;
i = j;
}