本章由高斯计算从1加到100的思想引入算法之间的比较.从而引入一个话题:什么是算法.算法其实就是解决特定问题求解步骤的描述,在计算机中表现为指令的有限序列,并且每条指令表示一个或者多个操作.
讲述了算法的概念,接下来就是要对它有一个深入的了解过程,于是,到了说说它的特性的时候了,算法的五个基本特性分别是:输入,输出,有穷性,确定性和可行性.其中,算法可以有零个或者多个输入,但一定要至少有一个输出,否则算法就失去意义了.有穷性则能保证算法不会无限制的重复下去,那么确定性呢?试想一个算法是有歧义的,那么怎么能保证我们要的结果会是预期的呢?因此,算法的确定性也必须要得到保证。如果算法不可行,那么这个算法也是没有意义的,只是一个空想.因此这几点必须满足.
设计算法,可以说世界上有多少人就会有多少种算法,因为每个人的想法都不一样,因此算法其实没有一个固定的答案,条条大路通罗马.但是衡量一个算法是否是好算法却是有一定的标准的。
好算法首先必须是正确的,这里说的正确,包含语法上的正确性,对于合法的输入结果能产生满足要求的输出结果,对于非法的输入能得到满足规格的提示说明,当然,最优的一条就是连刁难的数据都能有满足要求的输出结果。怎么说呢,比如计算两个数相加的算法,算法出来的第一点就是要满足语法不发生错误,其次我们该考虑输入两个数据的时候,能得到正确的相加结果,而不是1+1=1这样错误的输出,再者,当我们输入的不是数字而是字母的话,需要对这些非法的数据做出处理,最简单的就是提示用户输入有问题,程序跳出.第四点是最困难的,因为我们不可能逐一去验证所有的输入都得到正确的结果.
当算法满足了正确性的时候,我们可以舒一口气了,因为最重要的目标我们已经完成了.当然,这也许只是完成了目标,却未必就是好算法.假设你的算法出现了问题,而你自己未能发现,需要请求别人帮助的时候,你希望能尽快得到解决,而那个帮助你的人也并不想多花时间给你找错误,又假设你现在写了一个系统,多年后你想再回味下你写过的东西,我想不管是帮助你的人还是多年后的你自己,都不会希望看到一段让人摸不着头脑的代码吧.所以好算法的另一个衡量的标准就是这个算法的可读性.
满足了以上两点,这个算法算是不错的了,也许你会想那是不是还能有更优的算法呢?没错,同样是写一个加法的算法,满足了1+2不会等于2以后,你考虑过输入a和b做相加的结果么?a+b会是什么答案?或者a+1,b+1呢?显然,字母和数字要做四则运算是有问题的,此时,你该怎么解决呢?让程序自己崩溃?还是让它们计算出一个意想不到的结果?这个就关系到你算法的健壮性问题了。此时,你要思考的就是当用户输入了这些非法字符后,你能做些什么?假设一下,现在的你站在ATM机前,明明卡里只有200元,但是你想多取些钱花花,你摁下取款键然后输入了500,也许你会希望5张100的钱都能出来,但银行可不想遇到这样的损失.此时,别说500了,也许200你都暂时拿不到,除非你重新输入200.为什么呢?就好象我输入a,2两个数据,我希望得到a+2=100,这是不可能的,而要避免这种不可能,你就需要在程序中对此进行一些操作,比如遇到这样不讲理的用户,我们也跟着不讲理,你要计算a+2是吧,别做梦了,这个算法不和你玩了,弹出大大的字"你这个傻瓜,字母和数字怎么加?不和你玩了,程序5秒钟自动关闭".综上所述,健壮性其实就是对非法数据作出相关处理,而不是等着程序发生莫名其妙的结果.
恩,做的不错,现在的算法看起来很完美了,可是,这个算法的效率如何呢?拿开头高斯的故事来说,现在要完成一个从1加到100的算法,最简单的,我们能第一时间想到for循环,1+2=3,3+3=6,6+4=10.....4950+100=5050.于是很快的,写出了这样的算法:
1 int sum=0;
2 int n=100;
3 for(int i=1;i<=n;i++)
4 {
5 sum=sum + i;
6 }
7
8 Console.WriteLine("{0}",sum);
以上是其他所有小朋友写的算法,老师检查的时候露出了满意的笑容,但是突然老师发现有一个小朋友写的不是这样的,而是如下所示的代码:
1 int sum=0;
2 int n=100;
3 sum=(1+n)*n/2;
4 Console.WriteLine("{0}",sum);
这个小朋友就是高斯,老师看了半天,没发现哪里有错误,这真是一个好方法,为什么?因为for循环写出来的算法,交给计算机执行,该执行多少次就要执行多少次,但是这个就不一样了,不管n是多少,都能一次就得到答案.妙,实在是妙.
这又说明了好的算法具有时间效率高的特点.
其实,在现实生活中,我们都希望花最少的钱,用最短的时间,办最多的事,算法也是这样的思想,将大量的数据都放在内存中存储,早晚计算机会吃不消,所以我们也是希望放最少的东西来完成同样的任务。因此,好的算法也应该如此,在满足时间效率的同时,也能满足存储量低的需求.
这就是一个好的算法需要具备的几个特点:正确性,可读性,健壮性,时间效率高和低存储量.