PAT相关的基础知识
- 一.sort函数
- 二.set的用法
- 三.输出百分比
- 四.数的科学计数法
- 五.lower_bound和upper_bound函数用法
- 六.最大公约数
- 七.最小公倍数
- 八.分母的四则运算
- 九.素数
- 十.atoi和stoi函数 将数字字符串转换为int输出
- 十一.字符的大小写转换 tolower和toupper
- 十二.字符串的大小写转换 transform
- 十三.map的用法
- 十四.散列
- 十五.auto的用法
- 十六.通过前序遍历建立二叉线索树
- 十七.判断二叉树每个结点的树高
- 十八.整数转换为数组
- 十九.数组转换为整数
- 二十.将字符串翻转 reverse和reverse_copy函数
- 二十一.四舍五入
- 二十二.不大于(小于)自变量的最大整数
- 二十三.根据先序和中序遍历建树
- 二十四.给定先序和中序,返回后序的第一个结点
- 二十五.给定二叉树先序和中序,指出两个结点的最低公共祖先
- 二十六.数组复制 memcpy
- 二十七.专业名词中英文
- 二十八.树中的层序遍历
- 二十九.给定完全二叉树的层序遍历,要求从右子树开始输出所有叶结点的路径
- 三十.给定完全二叉树的层序遍历,要求从左子树开始输出所有叶结点的路径
- 三十一.cctype头文件的使用
- 三十二.并查集
- 三十三.C++保留小数
一.sort函数
下面记录最基础的sort
函数的用法:
#include <algorithm>//头文件
//最简单的比较函数
bool cmp(int a,int b)
{
return a<b; //注意大于小于
}
//复杂一点的比较函数
bool cmp2(Student a, Student b) {
if (a.score != b.score)
return a.score > b.score;
else if (a.solve != b.solve)
return a.solve > b.solve;
else return a.id < b.id;
}
int main()
{
int a[10];
for(int i = 0; i < 10; i++)
scanf("%d",&a[i]);
sort(a, a + 10, cmp);
return 0;
}
二.set的用法
set的特性是,所有元素都会根据元素的键值自动排序,set的元素不像map那样可以同时拥有实值(value)和键值(key),set元素的键值就是实值,实值就是键值。set不允许两个元素有相同的键值。
set的各成员函数列表如下:
-
begin()–返回指向第一个元素的迭代器
-
clear()–清除所有元素
-
count()–返回某个值元素的个数
-
empty()–如果集合为空,返回true
-
end()–返回指向最后一个元素的迭代器
-
equal_range()–返回集合中与给定值相等的上下限的两个迭代器
-
erase()–删除集合中的元素
-
find()–返回一个指向被查找到元素的迭代器
-
get_allocator()–返回集合的分配器
-
insert()–在集合中插入元素
-
lower_bound()–返回指向大于(或等于)某值的第一个元素的迭代器
-
key_comp()–返回一个用于元素间值比较的函数
-
max_size()–返回集合能容纳的元素的最大限值
-
rbegin()–返回指向集合中最后一个元素的反向迭代器
-
rend()–返回指向集合中第一个元素的反向迭代器
-
size()–集合中元素的数目
-
swap()–交换两个集合变量
-
upper_bound()–返回大于某个值元素的迭代器
-
value_comp()–返回一个用于比较元素间的值的函数
建立
#include <set>
set <int> list[51];//set的数组
set <int> list2;
遍历
set<int>::iterator it;
for(it = list2.begin(); it! = list2.end(); it++)
{
cout << *it;
}
反向遍历
set<int>::reverse_iterator it;
for(it = list.rbegin(); it != list.rend(); it++)
{
cout << *it;
}
注意反向遍历用的指针类型不同,所指向的也不同,虽然是反向遍历,但是指针还是++而非- -
查找
if( list2.find (findnum) != list2.end() )
{
cout<<" The number is in list2"<<endl;
}
三.输出百分比
printf("%.1f%% \n", 100 * (double)comnum);
四.数的科学计数法
数的情况有以下几种:
0
0.12345
0.0012345
123.45
12345
001234.5
0012345
首先判断数的指数
该判断分为小于1的数和大于等于1的数
小于1的数,小数点后面连续0的个数即为数的指数的负数
大于等于1的数,小数点前面的数的个数即为数的指数(正数)
但在此之前要去掉数最前面的0,避免它也被算入其中
接着判断底,底只是非0数开头的要求长度的字符串
例如上述数字中,要求0后面保留4位,则(以下皆是科学计数法0.
后面的数字)
0 -> 0000
0.12345 -> 1234
0.0012345 ->1234
123.45 ->1234
此时的底已经与小数点没有关系了
但要注意,当字符串的长度不足要求时,要在后面补上对应个数的0
接下来就是处理步骤:
数字是保存在字符串或者字符数组中的,这样才能保证对数的每一位直接处理
1.
把开头的0去掉
此时小于1的是就是小数点开头,大于等于1的数就是非0的数字开头
2.
通过上述判断数是小于1的数还是大于等于1
这要分开处理,因为小于1的数指数是负的,大于等于1的数指数是正的
3.
若该数是小于1的数
则将字符串开头的小数点和连续的0都删除并且记录0的个数
此时0的个数即为10^-k
中的k
例如:0.001234
-> 0.1234*10^-2
4.
若该数是大于等于1的数
则计算小数点之前的数的个数并记录
此时该个数即为10^k
中的k
例如:123.45
-> 0.12345*10^3
在这个部分还需要将小数点从字符串中去掉,方便后面底的提取
5.
判断了上述3和4,还需要判断输入的数是不是0,因为如果是0,则k是未知的,因为在第1步时已经把0去掉了
因此还需要判断是不是0,如果是0则指数k
为0
如何判断是不是0:判断字符串是不是空即长度是否为0即可
6.
最后就是底数的处理了
在剩下的字符串提取要求个数的字符,如果字符串的长度小于要求的个数则在后面补0
7.
最后处理得出的结果,底数和指数可以建立一个结构体保存
最后比较两个结构体的底和指数就可以了
代码:
struct science_num {
string di;
int zhi;
} na, nb;
science_num change(string a, int N) {
int k = 0;
science_num na;
na.zhi = 0;
na.di.clear();
//去除前导0
while (a.length() > 0 && a[0] == '0') {
a.erase(a.begin());
}
//若a是小于1的数
if (a[0] == '.') {
a.erase(a.begin());//将小数点删除
while (a.length() > 0 && a[0] == '0') {
a.erase(a.begin());//将小数点后面连续的0删除
na.zhi--;//记录0的个数
}
}
//若a不小于,找到可能存在的小数点并删除
else {
while (k < a.length() && a[k] != '.') {
k++;
na.zhi++;//记录小数点前数字的个数
}
if (k < a.length()) {
a.erase(a.begin() + k);
}
}
//若a为0,将指数置0
if (a.length() == 0) {
na.zhi = 0;
}
//预处理完毕,规格化
if (a.length() >= N) {
na.di.insert(na.di.begin(), a.begin(), a.begin() + N);//提取要求长度的字符串作为底
}
else {
na.di.insert(na.di.begin(), a.begin(), a.end());
for (int i = 0; i < N - a.length(); i++) {
na.di += '0';//当长度不满足要求的时候在后面补0
}
}
return na;//返回结果结构体
}
补充:字符串的处理
删除字符串指定位置的函数:
a.erase(a.begin() + k);
将字符串一部分添加到另一个字符串:
str1.insert(str1.begin(), str2.begin(), str2.begin() + N);
清空字符串:
str1.clear();
五.lower_bound和upper_bound函数用法
在从小到大的排序数组中
lower_bound(begin,end,num)
表示从数组的begin位置到end-1位置二分查找第一个大于或等于num的数字
upper_bound(begin,end,num)
表示从数组的begin位置到end-1位置二分查找第一个大于num的数字
在从大到小的排序数组中
lower_bound(begin,end,num,greater<type>())
表示从数组的begin位置到end-1位置二分查找第一个小于或等于num的数字
upper_bound(begin,end,num,greater<type>())
表示从数组的begin位置到end-1位置二分查找第一个小于num的数字
以上若找到返回该数字的地址,不存在则返回end
因此需要通过返回地址减去起始地址begin,得到该数字在数组中的下标
六.最大公约数
int gcd(int a,int b){
if(b == 0)
return a;
else
return gcd(b, a % b);
}
七.最小公倍数
辗转相除法求最小公倍数:
int lcm(int x,int y){
int a = 0, b = 0;
int temp = 0;
if(x < y)
{
temp = x;
x = y;
y = temp;
}
a = x * y;
while(y != 0)
{
b = x % y;
x = y;
y = b;
}
return a/x;
}
八.分母的四则运算
分数的表示和化简
分数的表示
对一个分数来说,最简洁的写法就是写成假分数的形式,无论分子比分母大或者小,都保留其原数
因此可以使用一个结构体来存储这种只有分子和分母的分数:
struct Fraction{
int up,down;
};
对这种表示制订三项原则:
1.使down为非负数,如果分数为负,那么令分子up负即可
2.如果该分数恰为0,那么规定其分子为0,分母为1
3.分子和分母没有除了1以外的公约数
分数的化简
分数的化简主要用来使Fraction变量满足分数表示的三项规定,因此此步骤也分为三步:
1.如果分母down为负数,那么令分子up和分母down都变为相反数
2.如果分子up为0,那么令分母down为1
3.约分:求出分子绝对值与分母绝对值的最大公约数d,然后令分子分母同时除以d
代码如下:
Fraction reduction(Fraction result){
if(result.down < 0)
{
result.up = -result.up;
result.down = -result.down;
}
if(result.up == 0)
{
result.down = 1;
}
else
{
int d = gcd(abs(result.up), abs(result.down));
result.up /= d;
result.down /= d;
}
return result;
}
分数的四则运算
分数的加法
对两个分数f1
和f2
,其加法计算公式为
result = ( f1.up * f2.down +f2.up * f1.down ) / (f1.down * f2.down)
代码如下:
Fraction add( Fraction f1, Fraction f2)
{
Fraction result;
result.up = f1.up * f2.down + f2.up * f1.down;
result.down = f1.down * f2.down;
return red