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

数据结构与算法五

2015-07-16 16:43 183 查看
很多问题来说,算法不是唯一的。同一个问题,可以有多种解决问题的算法。正因为算法不唯一,相对好的算法还是存在的。什么才叫好的算法呢?

首先一个算法必须具备以下性质:

算法首先必须是正确的,即对于任意的一组输入,包括合理的输入与不合理的输入,总能得到预期的输出。如果一个算法只是对合理的输入才能得到预期的输出,而在异常情况下却无法预料输出的结果,那么它就不是正确的。

算法必须是由一系列具体步骤组成的,并且每一步都能够被计算机所理解和执行,而不是抽象和模糊的概念。

每个步骤都有确定的执行顺序,即上一步在哪里,下一步是什么,都必须明确,无二义性。

无论算法有多么复杂,都必须在有限步之后结束并终止运行,即算法的步骤必须是有限的。在任何情况下,算法都不能陷入无限循环中。

一个问题的解决方案可以有多种表达方式,但只有满足以上4个条件的解才能称之为算法。

正确性

正确性:算法的正确性是指算法至少应该具有输入、输出和加工处理无歧义性、 能正确反映问
题的需求、能够得到问题的正确答案。

但是算法的“正确”通常在用法上有很大的差别,大体分为以下四个层次。

算法程序没有语法错误。

算法程序对于合法的输入数据能够产生满足要求的输出结果。

算法程序对于非法的输入数据能够得出满足规格说明的结果。

算法程序对于精心选择的,甚至刁难的测试数据都有满足要求的输出结果。

因此算法的正确性在大部分情况下都不可能用程序来证明,而是用数学方法证明的。证明一个复
杂算法在所有层次上都是正确的,代价非常昂贵。所以一般情况下, 我们把层次3作为一个算法
是否正确的标准。

可读性

可读性:算法设计的另一目的是为了便于阅读、理解和交流。

我们写代码的目的,一方面是为了让计算机执行,但还有一个重要的目的是为了便于他人阅

读,让人理解和交流,自己将来也可能阅读,如果可读性不好,时间长了自己都不知道写了些

什么。可读性是算法(也包括实现它的代码)好坏很重要的标志。

健壮性

一个好的算法还应该能对输入数据不合法的情况做合适的处理。比如输入的时间或者距离不应
该是负数等。

最后,好的算法还应该具备时间效率高和存储量低的特点。

时间效率指的是算法的执行时间,对于同一个问题,如果有多个算法能够解决,执行时间短的
算法效率高,执行时间长的效率低。

存储量需求指的是算法在执行过程中需要的最大存储空间,主要指算法程序运行时所占用的内
存或外部硬盘存储空间。

设计算法应该尽量满足时间效率髙和存储量低的需求。在生活中,人们都希望花最少的钱,用最短的时间,办最大的事,算法也是一样的思想,最好用最少的存储空间,花最少的时间,办成同样的事就是好的算法。

综上,好的算法,应该具有正确性、可读性、健壮性、髙效率和低存储量的特征。

算法的设计要注意效率,这里效率大都指算法的执行时间。一个用高级程序语言编写的程序在计
算机上运行时所消耗的时间取决于下列因素:

算法采用的策略、方法。

编译产生的代码质量。

问题的输入规模。

机器执行指令的速度

第1条当然是箅法好坏的根本,第2条要由软件来支持,第4条要看硬件性能。也就是说,抛开这些与计算机硬件、软件有关的因素,一个程序的运行时间,依赖于算法的好坏和问题的输入规模。所谓问题输入规模是指输入量的多少。此时你会看到,测定运行时间最可靠的方法就是计算对运行时间有消耗的基本操作的执行次数。运行时间与这个计数成正比。

我们不关心编写程序所用的程序设计语言是什么,也不关心这些程序将跑在什么样的计算机中,我们只关心它所实现的算法。这样,不计那些循环索引的递增和循环终止条件、变量声明、打印结果等操作,最终,在分析程序的运行时间时,最重要的是把程序看成是独立于程序设计语言的算法或一系列步骤。

我们可以这样认为,随着n值的越来越大,它们在时间效率上的差异也就越来越大。

算法(Algorithms)的复杂度(Complexity)是指运行一个算法所需消耗的资源(时间或者空间)。同一个算法处理不同的输入数据所消耗的资源也可能不同,所以分析一个算法的复杂度时,主要有三种情况可以考虑,最差情况(Worst
Case)下的,平均情况(Average Case)的, 最好情况(Best Case)下的。

最坏情况运行时间是一种保证,那就是运行时间将不会再坏了。在应用中,这是一种最重要的需求,通常,除非特别指定,我们提到的运行时间都是最坏情况的运行时间。

而平均运行时间也就是从概率的角度看,这个数字在每一个位置的可能性是相同的,所以平均的查找时间为n/2次后发现这个目标元素。平均情况更能反映大多数情况下算法的表现。平均情况分析就是对所有输入尺寸为n的输入,让算法运转一遍,然后取它们的平均值。当然,实际中不可能将所有可能的输入都运行一遍,因此平均情况通常指的是一种数学期望值,而计算数学期望值则需要对输入的分布情况进行假设。

平均运行时间是所有情况中最有意义的,因为它是期望的运行时间。也就是说,我们运行一段程序代码时,是希望看到平均运行时间的。可现实中,平均运行时间很难通过分析得到,一般都是通过运行一定数量的实验数据后估算出来的。

有时候我们还需要知道最好情况是什么,这有两层意义:一是我们想知道如果运气好,能好到什么程度;二是如果我们能够证明好运气与我们同在,当然需要知道运气好的时候算法表现如何。这种最好分析就是在给定输入规模的时候,看看哪种输入能使算法的运行最有效率。当然,有人认为这种最好情况分析有点假:我们可以操控输入来使一个本来很慢的算法表现得很快,从而达到蒙蔽人的效果。

对算法的分析,一种方法是计算所有情况的平均值,这种时间复杂度的计算方法称为平均时间复杂度。另一种方法是计算最坏情况下的时间复杂度,这种方法称为最坏时间复杂度。一般在没有特殊说明的情况下,都是指最坏时间复杂度。

最差情况下的复杂度是所有可能的输入数据所消耗的最大资源,如果最差情况下的复杂度符合我们的要求,我们就可以保证所有的情况下都不会有问题。

某些算法经常遇到最差情况。比如一个查找算法,经常需要查找一个不存在的值。

也许你觉得平均情况下的复杂度更吸引你,可是平均情况也有几点问题。第一,难计算,多数算法的最差情况下的复杂度要比平均情况下的容易计算的多,第二,有很多算法的平均情况和最差情况的复杂度是一样的.
第三,什么才是真正的平均情况?如果你假设所有可能的输入数据出现的概率是一样的话,也是不合理的。其实多数情况是不一样的。而且输入数据的分布函数很可能是你没法知道。

考虑最好情况的复杂度更是没有意义。几乎所有的算法你都可以稍微修改一下,以获得很好的最好情况下的复杂度(要看输入数据的结构,可以是O(1))。怎样修改呢?
预先计算好某一输入的答案,在算法的开始部分判断输入,如果符合,给出答案。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: