补充
cin与cout
cin
cin是c和in的合成词,采用输入运算符“>>”来进行输入,cin的输入不指定格式,也不需要加取地址运算符&,直接写变量名即可。如果同时读入多个变量,只需要往后面使用>>进行扩展。如果想要读入一整行,则需要使用getline函数。如果是string容器,整行输入方式则有所不同,可见代码示例
cout
cout是c和out的合成词,其使用方法和cin几乎一致,只不过使用的是输出运算符<<。需要注意的是,输出是中间没有空格,若需要间隔变量得手动添加空格。也可以在中间输出字符串
对于cout来说,换行的方式有两种:一是用“\n”来进行换行,二是使用endl来表示换行(end line的缩写)
如果想要控制double型的精度,需要在输出之前加上一些东西,并且要加上#include <iomanip>头文件。例如输出小数点后两位,以下代码输出123.46
浮点数的比较
等于运算符(==)、大于运算符(>)、小于运算符(<)、大于等于运算符(>=)、小于等于运算符(<=)
由于计算机中采用有限位的二进制编码,因此浮点数在计算机中的存储并不总是精确的,在经过大量计算后,浮点数在计算机中的存储存在误差,此时,需要引入一个极小数eps对这种误差进行修正。经验表明,eps取是一个合适的数字,即对大多数情况不会漏判也不会误判。有了eps后,可以对误差进行修正,例如对于等于运算符而言,如果一个数a落在[b-eps, b+eps]的区间中,就判断a == b,可以把eps定义为常量1e - 8,把比较操作写成宏定义的形式
事实上,如果没有经过容易损失精度的计算,就不需要考虑误差,可以直接比较,但是当一个变量进行了误差较大的运算后,精度的损失就不可忽视了
圆周率
由可知
,所以只需要把
写成常量
即可
需要注意的两点:①由于精度原因,在经过大量运算后,可能一个变量中存储的0是一个很小的负数,这时如果对其开根号sqrt,就会因不在定义域内而出错。同样的问题还出现在asin(x)当x存放+1,acos(x)当x存放-1时。这种情况需要用eps使变量保证在定义域内。②在某些由编译环境产生的原因下,本应为0.00的变量在输出时会变成-0.00.这个问题是编译环境自身的bug,只能把结果存放到字符串中,然后与-0.00进行比较,如果比对成功,则加上eps来修正为0.00
复杂度
时间复杂度
时间复杂度是算法需要执行基本运算的次数所处的等级,其中基本运算就是类似加减乘除这种计算机可以直接实现的运算。时间复杂度是评判算法时间效率的有效标准
n次基本运算与2n次基本运算,当n的规模增大时的增长趋势是相同的(都是线性增长),于是把称作它们的时间复杂度,表示消耗的时间随着规模n的增长而线性增长。显然,是否是线性增长与前面的系数无关,因此
和
是等价的。
在时间复杂度中,高等级的幂次会覆盖低等级的幂次,因此成立。显然
会趋近于
,其中c是一个常数,我们把这个常数称为算法时间复杂度的常数,当有些算法实现较为复杂时,其常数会比较大,这时即便时间复杂度相同(注意讲时间复杂度时一般是不带系数的),其性能也会有较大差距
表示其消耗的时间随着规模n的增大而呈平方级增长常数复杂度。常数复杂度
则表示算法消耗的时间不随规模的增长而增长。则有
成立
对一般的OJ系统来说,一秒能承受的运算次数大概是~
空间复杂度
空间复杂度表示算法需要消耗的最大数据空间。如果一个算法消耗的最大数据空间是一个二维数组,那么这个算法的空间复杂度是。对一般的应用来说,空间都是足够用的,所以空间复杂度重要性一般没有时间复杂度那么大。
的空间复杂度是指算法消耗的空间不随数据规模的增大而增大
考虑到空间一般够用,因此常常采用以空间换时间的策略,如散列法(hash)(哈希函数的常见使用)
编码复杂度
编码复杂度是一个定性的概念,并没有什么量化的标准。如果使用了冗长的算法思想,那么代码量将会非常巨大,其编码复杂度就会非常大