准备 PAT 竞赛时自己总结的实用函数,搞过 OJ 的应该都有一套自己总结的算法秘籍(小抄),这种东西主观性比较强,自己搞的才看的懂,发出来做个记录吧
cmath 头文件
其针对的参数大多为 double,所有进行整型判断的时候需要进行转换:(double)int;
方法
含义
fabs()
绝对值
floor()、ceil()
向下、向上取整
pow(r, p)
幂值: r p r^p r p
sqrt()
开根
round()
四舍五入取整
log()
以 e 为底的对数
并没有以任意数为底的求对数函数,但可以采用换底公式: l o g a b = l o g e b / l o g e a log_ab=log_eb/log_ea l o g a b = l o g e b / l o g e a
climits 头文件
最常使用的是对最大最小值的赋予: INT_MAX/MIN
1 2 3 4 int max = INT_MIN, min = INT_MAX; cout << max << " " << min << endl;
bitset 头文件
二进制操作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 bitset<5> b ("11" ) ; for (int i = 0 ; i < 5 ; i++) cout << b[i]; cout << endl << b.any (); cout << endl << b.none (); cout << endl << b.count (); cout << endl << b.size (); cout << endl << b.test (2 ); b.set (4 ); b.reset (); b.reset (3 ); b.flip (); unsigned long a = b.to_ulong ();
进制转换函数
手动写法
1 2 3 4 5 6 7 8 9 10 11 12 13 int len = 0 , arr[100 ];do { arr[len++] = n % radix; n = n / radix; } while (n != 0 ); for (int i = len - 1 ; i >= 0 ; i--){ n = n * radix + arr[i]; }
输出格式
在使用 头文件时可以根据输出关键字进行进制的转换
1 2 3 4 cout << "35 的 8 进制:" << oct << 35 << endl; cout << "35 的 10 进制 " << dec << 35 << endl; cout << "35 的 16 进制:" << hex << 35 << endl; cout << "35 的 2 进制: " << bitset <8 >(35 ) << endl;
strtol()函数
任意进制转换为十进制(str→long int) ,其格式为: long int strtol(const char *nptr, char **endptr, int base)
,base 是要转化的数的进制,非法字符会赋值给 endptr,nptr 是要转化的字符
因为是 C 语言自带的函数,所以字符串只能用 char 数组的方式读入(也可以字符串读入然后转换成字符数组)
1 2 3 4 5 6 7 char a[20 ]="10549stend#12" ; char *stop; int ans=strtol (a, &stop, 8 ); printf ("%d\n" ,ans); printf ("%s\n" , stop);
itoa()函数
十进制转换为任意进制(int→str) ,其格式为: char
itoa(int value,char
string,int radix);
,radix 是要转化的数的进制
因为是 C 语言自带的函数,所以字符串只能用 char 数组的方式读入(也可以字符串读入然后转换成字符数组)
1 2 3 4 int num = 10 ; char str[100 ]; _itoa(num, str, 2 ); printf ("%s\n" , str);
sprintf()函数
也是将一个 10 进制数转换为指定格式的 n 进制字符串 ,函数原型: int sprintf(char *buffer, const char *format, [ argument] … )
1 2 3 4 5 6 7 8 9 10 11 char s[100 ]={0 };sprintf (s, "%d" , 123 ); sprintf (s, "%4d%4d" , 123 , 4567 ); sprintf (s, "%8o" , 123 ); sprintf (s, "%8x" , 4567 ); sprintf (s, "%10.3f" , 3.1415626 ); int i = 100 ;sprintf (s, "%.2f" , i); sprintf (s, "%.2f" , (double )i);
cstring 头文件
函数初始化数组
给数组初始化时,可以使用 memset()函数进行填充,而不用 for 循环遍历,其格式为: memset(数组名, 初始值,sizeof(数组名));
其在头文件 中,只用 memset()函数为数组赋 0 或 -1 时使用
也可对二维数组和多维数组进行初始操作
1 2 3 4 5 6 int arr[10 ];memset (arr, 0 , sizeof (arr));for (auto i = 0 ; i < 10 ; i++){ cout << arr[i] << " " ; }
字符串转换数组
字符串转换为字符数组需要使用 中的 strncpy 方法将字符串内容挨个拷贝进数组中
字符数组转换为字符串可以直接进行赋值转换
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 #include <iostream> #include <cstring> using namespace std; int main () { string s = "aaaa vvva" ; char a[10 ]; strncpy (a, s.c_str (), s.length ()); for (int i = 0 ; i < 10 ; i++) cout << a[i]; cout << endl; char arr[] = "123 45sdf" ; string str = arr; cout << str << endl; system ("pause" ); return 0 ; }
tostring 函数
在头文件 中,也可以不用
作用是将其他类型的数据转换为 string 型
1 2 3 4 5 6 string s1 = to_string (123 ); cout << s1 << endl; string s2 = to_string (4.5 ); cout << s2 << endl; cout << s1 + s2 << endl; printf ("%s\n" , (s1 + s2).c_str ());
string 转换成 int,double 可以使用 stoi 和 stod 方法,其含义为 string to int,其他数据类型也适用只要将最后一个字母写成目标类型的首字母
1 2 3 4 5 6 7 8 string str = "123" ; int a = stoi (str); cout << a << endl; str = "123.44" ; double b = stod (str);cout << b << endl;
algorithm 头文件
数学函数
max(x,y)、min(x,y)函数用来返回两个数(可以是浮点)中较大或较小的那个,如果是判断三个数的最大值可以写成: max(a,max(b,c))
abs()只能是整数,浮点数可以用 下的 fabs()
swap()用来交换两个数的值
sort 函数
sort 排序函数在头文件 中,主要是对数组进行排序,格式为: sort(数组头,数组尾,规则 cmp);
cmd 的排序规则的格式是返回一个大小判断的 bool 值,不能有 = 号,sort 是不稳定的排序
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 #include <iostream> #include <algorithm> #include <vector> using namespace std;bool cmp (int a, int b) { return a > b; } int main () { vector<int > v (10 ) ; for (int i = 0 ; i < 10 ; i++) { cin >> v[i]; } sort (v.begin (), v.end ()); int arr[10 ]; for (int i = 0 ; i < 10 ; i++) { cin >> arr[i]; } sort (arr, arr + 10 , cmp); system ("pause" ); return 0 ; }
struct 的 sort
结构体中可能会对多个变量进行比对,这就需要进行自定义的 cmp 函数
有一个学生结构体,要对学生进行排序时按照如下方法:当成绩不同时按从大到小排列,若成绩相同,对相同者进行学号从小到大排列
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 struct stu { int number; int score; }; bool cmp (stu a, stu b) { if (a.score != b.score) return a.score > b.score; else return a.number < b.number; } bool cmp (stu a, stu b) { return a.score != b.score ? a.score > b.score : a.number < b.number; }
cmp_char[]
字符数组的排序不能像字符串那样直接进行比较,需要使用 中的 strcmp()函数
1 2 return (strcmp (a.name, b.name) < 0 ); return (strcmp (a.name, b.name) > 0 );
项式 cmp
PAT(advance)中的 T1038 中就要将字符串使用多项式相加的规则进行排序
1 2 3 4 5 6 7 bool cmp (string a, string b) { return a + b < b + a; }
reverse()函数
中的反转函数,通过指针或迭代器用来反转相应范围内的数,应用于数组和字符串较多
用来反转字符串非常方便
1 2 3 4 5 6 char arr[8 ] = {'1' , '2' , '3' , '4' , '5' , '6' , '7' , '8' };reverse (arr, arr + 4 );string str; getline (cin, str);reverse (str.begin (), str.end ());cout << str << endl;
next_pernumtation()
当前序列的下一个全排列,可配合 do…while()循环输出一个序列的全排列
1 2 3 4 5 6 7 int arr[3 ] = {1 , 2 , 3 };do { cout << arr[0 ] << " " << arr[1 ] << " " << arr[2 ] << endl; } while (next_permutation (arr, arr + 3 ));
max_element()及 min_element()函数
中的求最大最小值的函数,可对普通数组和 vector 数组进行使用
返回的是迭代器或指针,所以加上取值符 *,若求下标则用返回的结果减去数组的起始位置即可
1 2 3 4 5 6 7 8 9 10 11 vector<int > vec; int maxValue = *max_element (v.begin (),v.end ()); int minValue = *min_element (v.begin (),v.end ());int maxPosition = max_element (v.begin (),v.end ()) - v.begin (); a[]={1 ,2 ,3 ,4 ,5 ,6 }; int maxValue = *max_element (a,a+6 ); int minValue = *min_element (a,a+6 ); int maxPosition = max_element (a,a+6 ) - a;
初始化数组
memset()函数
给数组初始化时,可以使用 memset()函数进行填充,而不用 for 循环遍历,其格式为: memset(数组名, 初始值, sizeof(数组名));
其在头文件 中,只用 memset()函数为数组赋 0 或 -1 时使用
也可对二维数组和多维数组进行初始操作
1 2 3 4 5 6 7 8 9 int arr[10 ]; memset (arr, 0 , sizeof (arr)); for (auto i = 0 ; i < 10 ; i++){ cout << arr[i] << " " ; }
fill()函数
与 memset 不同的是可以对数组不同范围内赋予任意值,格式: fill(起,始,初始值)
1 2 int arr[10 ];fill (arr + 2 , arr + 5 , 234 );
find 函数
find()函数的具体实用是可以返回一个数组(包括动态)中某个特定元素的指针(迭代器),因为数组的存储空间是连续的,用当前指针(迭代器)去减去开始的指针(迭代器)得到的就是数组中该元素的下标
1 2 3 4 5 6 7 8 9 10 int a[] = {1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 };int a_length = sizeof (a) / a[0 ]; vector<int > b{10 , 20 , 30 , 40 , 50 }; int *a_head = a; int *a_position = find (a, a + a_length, 6 ); cout << a_position - a_head << endl; auto b_position = find (b.begin (), b.end (), 30 ); cout << b_position - b.begin () << endl;
binary_search()
用以实现二分查找: binary_search(first,last,val)
,直接使用 find 函数也可,但如果查找数组中第一个大于 X 的数就不好实现了,所以二分查找又延伸出边界的查找
1 2 int a[100 ] = {4 , 10 , 11 , 30 , 69 , 70 , 96 , 100 };int b = binary_search (a, a + 9 , 4 );
查找边界
lower_bound()和 upper_bound()函数作用的对象是一个有序数组或容器,其格式为: lower_bound(first, last, val)
,返回数组或容器中第一个小于(或大于)val 的值的位置(指针或迭代器),若获取下标用其返回的位置减去起始位置即可
1 2 3 4 5 6 7 8 9 10 11 vector<int > v = {2 , 5 , 1 , 3 , 7 , 6 , 9 , 5 }; sort (v.begin (), v.end ());int up_position = upper_bound (v.begin (), v.end (), 6 ) - v.begin ();cout << v[up_position] << endl; int arr[10 ] = {3 , 5 , 6 , 2 , 7 , 9 , 1 , 2 , 6 , 8 };sort (arr, arr + 10 );int low_position = lower_bound (arr, arr + 10 , 7 ) - arr - 1 ;cout << arr[low_position] << endl;
cctype 头文件
就是 C 语言中的 <ctype.h> 头文件,里边包含一些类型判断函数非常方便
有时不进行头文件引用也可以进行函数的使用
1 2 3 4 5 6 7 8 9 10 11 12 char c;cin >> c; if (isalpha (c)){ cout << "c is alpha" ; } if (islower (c)){ cout << endl << "islow" ; }
其他的判断函数还包括:
函数名
意义
isalpha
字母(包括大写、小写)
islower
小写字母
isupper
大写字母
isalnum
字母(大写、小写)+ 数字
isblank
space 和 \t
isspace
space、\t、\r、\n
此外还有 tolower 和 toupper 方法用来将字符转换为大写或小写
1 2 3 4 5 char c = 'A' ;char t = tolower (c); cout << t << endl;