您的位置:首页 > 理论基础 > 数据结构算法

数据结构与算法(一)怎么判断算法的好坏

2019-08-03 23:15 721 查看
版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。 本文链接:https://blog.csdn.net/qq_40309483/article/details/98379697

怎么判断算法的好坏

一 评价的的指标

数据结构与算法最直观的目标就是要提高代码的性能。性能体现有两点:快和省。

二 怎么做评价

1.原始的评价方式

那么代码写好了,怎么知道它够不够快,够不够省?

最简单的方法,就是拉出来溜溜。官方点叫事后统计法。直接在把代码跑一遍,统计跑了多久,监控花了多少内存。

这种方法看起来没毛病,不过真正去实践的话,会发现有两个弊端:
1)我在我的电脑(i9处理器)代码跑了1s,我说我写的代码真不错。别人拿过去在他的电脑(i3处理器),代码跑了5s,他说这代码写的真垃圾。

结论就是测试结果很依赖测试环境。

2)我写的算法从头开始找数据,目标数据刚好在第一个,我花一次就找到,别人写的算法从尾巴开始找数据,目标数据刚好在第一个,花了n次找到。我能说我的算法优于别人的吗?目标数据这次刚好在第一个,下次在最后一个呢?

以上的例子可能不太恰当,不过结论是一样的:测试结果很依赖具体的测试数据。

2.改进的评价的方法–时间复杂度,复杂度

2.1代码的快慢程度–时间复杂度

不妨做个大胆的假设:每行代码执行的时间都一样,为 unit_time。
那么看看代码跑一次一共执行了多少行才得出结果不就可以评判它的快慢程度吗?
这个方法简单粗暴,不管在什么机子上跑都一样,比较公平。

那当测试的规模变化了,怎么去公平的评价呢?

先来看一个规律。

根据改进的评价方法,有人总结了一个规律:所有代码的执行时间 T(n) 与每行代码的执行次数 n 成正比。

简洁点用公式表达这个规律就是:T(n)=O( f(n) )
其中T(n)就是代码执行的时间,n代表数据规模的大小,f(n)代表每行代码总共执行次数。O代表f(n)与T(n)成正比关系。

其中O( f(n) )并不是代表代码真正的执行时间,否则用f(n)代码的执行次数去乘以一个固定的单位时间值就可以了,它代表的是代码执行时间随数据规模增长的变化趋势。O( f(n) )就叫做渐进时间复杂度,简称时间复杂度。

第一次看“它代表的是代码执行时间随数据规模增长的变化趋势”这次话,感觉不像是人话,太抽象。那就举个例子:
有两个算法:
算法A的相对时间规模是T(n)= 100n,时间复杂度是O(n)
算法B的相对时间规模是T(n)= 5n^2,时间复杂度是O(n ^ 2)
那哪个算法比较快?
这个问题其实其实没有肯定的答案,测试结果受测试数据规模的影响,
当n=1时,算法A跑100次,算法B跑5次;
当n=1 00时,算法A跑1万次,算法B跑5万次。

所以要想摆脱测试结果规模的影响做出评判,就得用一个指标来表示随着测试数据规模的增长,代码执行时间是怎么变化的。这样就可以分析在不同的应用场合采样什么样的算法比较合适。

怎么分析时间复杂度

总的原则,就是“成大事不拘小节”,只关注重点部分。具体怎么做的呢?
1)如果运行时间是常数量级,用常数1表示;
例如 T(n) = 2------------------------T(n) = O(1)
2)只保留时间函数中的最高阶项,同时省去最高阶项前面的系数。
例如 T(n) = 0.5n^2 + 0.5n-----------------T(n)= n^2

常见的时间复杂度

1)O(1)
一般情况下,只要算法中不存在循环语句、递归语句,即使有成千上万行代码,其时间复杂度也是O(1)。
其实这种情况就是代码不受测试数据的影响,想知道代码的快慢比较代码行数即可。
2)O(logn)、O(nlogn)
来看一段代码

i=1;
while (i <= n)  {
i = i * 2;
}

这段代码的时间复杂度就是O(logn),至于底数为2,还是3,不重要,因为对数可以相互转换(太纠结的话可以去看看其他教程)。
3) O(m+n)、O(m*n)
这种情况也很简单,有两种数据数据规模,例如两个独立的循环代码块,一个循环m次,一个循环n次,那么时间复杂度就是 O(m+n)

几种时间复杂度增长速度对比

从慢到快依次是:O(1)、O(logn)、O(n)、O(nlogn)、O(n^2)

2.2 代码执行时占用的内存大小–空间复杂度

前面时间复杂度说的是随着测试数据规模的增长,算法执行时间的变化。
对应的,空间复杂度说的是随着测试数据规模的增长,算法存储空间的变化。比如新建一个变量,意味着申请了一块存储空间。分析空间复杂度比时间复杂度简单多了。一般就着几种类型:O(1)、O(n)、O(n2 )。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: