c++部分笔记

输出格式

%.mf可以让浮点数保留m位小数输出,这个“保留”使用的是精度的“四舍六入五成双”规则。若题目没有明确要求“四舍五入”,则就用这个格式来输出;若明确要求,则需要用到round函数。

long long类型赋初始值

若初值大于2^31-1,则需要在初值后面加LL,否则会编译错误。

运算符优先级

取模运算符的优先级 等于 除法运算符

位运算符优先级没有算数运算符高

%与/的输出方式

algorithm库

        有max()、min()、abs()、swap()、fill()等函数

reverse()函数

        reverse(it1, it2)可以将数组指针在[it1, it2)之间的元素或容器迭代器在[it1, it2)范围内的元素进行反转(直接对原数组进行修改)

next_permutation()函数

// next_permutation()给出一个序列在全排列中的下一个序列
#include <cstdio>
#include <algorithm>
using namespace std;
int main() {
    int a[10] = {1,2,3};
    do {
        printf("%d%d%d\n",a[0],a[1],a[2]);
    }while(next_permutation(a,a+3));  // next_permutation已经达到全排列最后一个时会返回false
    return 0;
}

sort()函数——实现vector、string容器的排序

// 对vector排序
#include <cstdio>
#include <vector>
#include <algorithm>
using namespace std;
bool cmp(int a,int b) {
    return a>b;
}
int main() {
    vector<int> myVector;
    myVector.push_back(3),myVector.push_back(1),myVector.push_back(2);
    sort(myVector.begin(),myVector.end(),cmp);
    for(int i=0; i<3; i++)
        printf("%d ",myVector[i]);   // 输出结果是 3 2 1
    return 0;
}
// 对string进行排序
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
bool cmp(string a,string b) {
    return a.length() < b.length();
}
int main() {
    string str[3] = {"bbbb","cc","aaa"};
    sort(str,str+3,cmp);
    for(int i=0; i<3; i++)
        cout<<str[i]<<" ";   // 输出结果是 cc aaa bbbb
    return 0;
}

lower_bound()和upper_bound()函数

  • 这两个函数需要用在一个有序的数组或容器中
  • lower_bound(first, last, val)用来寻找在数组或容器的 [first, last) 范围内第一个值大于或等于val的元素的位置,如果是数组,则返回该位置的指针;如果是容器,则返回该位置的迭代器。
  • upper_bound(first, last, val)用来寻找在数组或容器的 [first, last) 范围内第一个值大于val的元素的位置,如果是数组,则返回该位置的指针;如果是容器,则返回该位置的迭代器。
  • 显然,如果数组或容器中没有需要寻找的元素,则两个函数均返回可以插入该元素的位置的指针或迭代器(即假设存在该元素时,该元素应该在的位置)。
  • 两个函数的复杂度均为O(log(last-first))。
// 如果只想获得欲查找元素的下标,就可以不使用临时指针
// 而直接令返回值减去数组首地址即可
#include <cstdio>
#include <algorithm>
using namespace std;
int main() {
    int a[10] = {1,2,2,3,3,3,5,5,5,5};
    // 寻找3,输出的结果是[3,6)
    printf("[%d,%d)",lower_bound(a,a+10,3)-a,upper_bound(a,a+10,3)-a);
    return 0;
}

math.h库

fabs函数

        与algorithm库下的abs函数相比,fabs函数用于求浮点型的绝对值

三角函数

数组申请空间的方式

memset和fill

字符数组

字符数组可以通过直接赋值字符串来初始化(仅限于初始化,程序其他位置不允许这样直接赋值整个字符串)。

用printf输出string类型

string str="123";
printf("%s",str.c_str());  // c_str()函数将string类型变为char数组

三个字符串头文件的区别

  • <string.h>是旧的C 头文件,对应的是基于char*的字符串处理函数;
  • <string>是包装了std 的C++头文件,对应的是新的string 类;
  • <cstring>是对应于旧C 头文件的std 版本,实际上只是在一个命名空间std中include了 <string.h>
  • 一般一个C++的老的带“.h”扩展名的库文件,比如iostream.h,在新标准后的标准库中都有一个不带“.h”扩展名的相对应(除了string库以外),区别除了后者的好多改进之外,还有一点就是后者的内容都塞进了“std”名字空间中
  • 将以前的C的头文件转化为C++的头文件后,有时加上c的前缀表示来自于c,例如cmath就是由math.h变来的

puts和gets

字符数组的存放方式

sscanf与sprintf

sscanf与sprintf是处理字符串问题的利器,主要对char数组进行操作。

scanf("%d",&n);等价于scanf(screen,"%d",&n);

printf("%d",n);等价于printf(screen,"%d",n);

可以发现scanf的输入其实是把screen的内容以"%d"的格式传输到n中(即从左至右),而printf的输出则是把n以"%d"的格式传输到screen上(即从右至左)。

sscanf与sprintf跟上面的格式是相同的,只不过把screen换成了字符数组。

sscanf(str,"%d",&n);

sprintf(str,"%d",n);

sscanf还支持正则表达式,如果配合正则表达式来进行字符串的处理,那么很多字符串的题目都将迎刃而解。

以数组作为函数参数

数组作为参数时,在函数中对数组元素的修改就等同于是对原数组的修改(这与普通变量的传参不同)。

不过,虽然数组可以作为参数,但是却不允许作为返回类型出现。如果想要返回数组,可以将想要返回的数组作为参数传入。

指针

指针是一个unsigned类型的整数。

指针相减

使用指针变量作为函数参数,视为把变量的地址传入函数,如果在函数中对这个地址中的元素进行改变,原先的数据就会确实地被改变。

 在访问指针对应地址的存放的具体值前,要确保指针被赋予初始值,否则指针会随机指向某个地址(可能是系统工作区间,这是很危险的)。

引用

引用就相当于给原来的变量取了个别名,这样旧名字跟新名字其实都是指同一个东西,且对引用变量的操作就是对原变量的操作。

引用是产生变量的别名,因此常量不可使用引用。若阅读代码时碰到了引用,却对其含义不甚了解时,不妨先把引用去掉,看看其原意是什么,然后再加上引用,这样会容易理解很多。

结构体

结构体里面能定义除了自己本身(这样会引起循环定义的问题)之外的任何数据类型。不过虽然不能定义自己本身,但可以定义自身类型的指针变量。

输入输出

getline的使用

浮点数大小的比较

自定义priority_queue的排序规则

#include <iostream>
#include <string>
#include <queue>
using namespace std;
struct fruit {
    string name;
    int price;
    fruit(string n,int p):name(n),price(p) {}
};
struct cmp {
    // 当结构体fruit内的数据较为庞大(例如出现了字符串或数组),建议使用引用来提高效率(在参数前后加上const、&)
    bool operator () (const fruit &fx,const fruit &fy) {  // 重载小于号
        return fx.price>fy.price;
    }
};
int main() {
    priority_queue<fruit, vector<fruit>, cmp> myQueue;
    myQueue.push(fruit("桃子",3));
    myQueue.push(fruit("梨子",4));
    myQueue.push(fruit("苹果",1));
    cout<<myQueue.top().name;  // 使用top()函数前,要确保队列不为空
    return 0;
}

排序

简单选择排序

对于待排序数组arr[n],总共需进行n趟操作(1<=i<=n),每趟操作选出待排序部分[i, n]中最小的元素,令其与arr[i]交换。因此总的复杂度为O(n^2)。

插入排序

是将待插入元素一个个插入初始已有序部分中的过程,而插入位置的选择遵循了使插入后仍然保持有序的原则,具体做法一般是从后往前枚举已有序部分来确定插入位置。

散列

将元素通过一个函数转换为整数,使得该整数可以尽量唯一地代表这个元素。

常见的散列函数

  1. 直接定址法
  2. 平方取中法
  3. 除留余数法

解决冲突的方法

  1. 线性探查法
  2. 平方探查法
  3. 链地址法

可以使用标准模板库中的map来直接使用hash的功能(C++11 以后可以用unordered_map,速度更快)。在实际机试中,一般不需要自己实现上面解决冲突的方法。 

字符串hash初步

如何将一个二维整点P的坐标映射为一个整数,使得该整点P可以由该整数唯一地代表?

假设P(x,y),其中0<=x,y<=Range,那么令hash函数为H(P) = x*Range + y,这样对数据范围内的任意两个整点P1, P2,  H(P1)都不会等于H(P2),  就可以用H(P)来唯一地代表该整点P,接着便可以通过整数hash的方法来进一步映射到较小的范围内。

字符串hash是指将一个字符串S映射为一个整数,使得该整数可以尽可能唯一地代表字符串S。

假设字符串均由A~Z构成,在这个基础上不妨把A~Z视为0~25,这样就把26个大写字母对应到了二十六进制中。接着,按照将二十六进制转换为十进制的思路,由进制转换的结论可知,在进制转换过程中,得到的十进制肯定是唯一的,由此便可实现将字符串映射为整数的需求(注意:转换成的整数最大为26^len-1,其中len是字符串的长度)。

显然,如果字符串S的长度比较长,那么转换成的整数也会很大,因此需要注意使用时len不能太长。如果字符串出现了小写字母,那么可以把A~Z作为0~25,而把a~z作为26~51,这样就变成了五十二进制转换为十进制的问题。

而如果出现了数字,一般有两种处理方法:

  • 按照小写字母的处理方法,增大进制数至62。
  • 如果保证在字符串的末尾是个确定个数的数字,那么就可以把前面的英文字母的部分按上面的思路转换为整数,再将末尾的数字直接拼接上去。

生成随机数

基本步骤

  1. 首先,需要stdlib.h和time.h头文件
  2. 然后加入语句"srand((unsigned)time(NULL));"   【这个语句将生成随机数的种子,srand()用于初始化随机种子】
  3. 然后在需要使用随机数的地方使用rand()函数

控制随机数范围的方法

        rand()函数只能生成[0, RAND_MAX]范围内的整数(RAND_MAX是stdlib.h中的一个常数,在不同系统环境中,该常数的值有所不同),若想要输出给定范围[a, b]内的随机数,需要使用rand()%(b-a+1)+a。但是该公式只对左右端点相差不超过RAND_MAX的区间的随机数有效,如果需要生成更大范围的随机数,有如下几种方法:

  1. 多次生成rand随机数,然后用位运算拼接起来(或者直接把两个rand随机数相乘)
  2. 随机选每一位数位的值(0~9),然后拼接成一个大整数
  3. 先用rand()生成一个[0, RAND_MAX]范围内的随机数,然后用这个随机数除以RAND_MAX,这样就会得到一个[0, 1]范围内的随机数。我们只需用这个浮点数乘以范围长度(b-a+1),再加上a即可。    round(1.0*rand()/RAND_MAX*(right-left)+left)

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值