很多开发者都知道“程序=数据结构+算法”这个著名的公式,单曲并不真正明白算法的定义或概念。究竟什么是算法呢?从字面意义上理解,算法即用于计算的方法,通过这种方法可以达到预期的计算结果。
一、算法特征
一个典型的算法一般都可以从中抽象出5个特征:又穷性、确切性、输入、输出和可行性。下面详细分析这5个特征。
有穷性:算法的指令或步骤的执行次数是有限的,执行时间也是有限的。
确切性:算法的每一个指令或步骤都必须又明确的定义和描述。
输 入:一个算法应该又相应的输入条件,用来刻画运算对象的初始情况。
输 出:一个算法应该又明确的结果输出。这是容易理解的,因为没有得到结果的算法毫无意义。
可行性:算法的执行步骤必须是可行的,且可以在有限时间内完成。
二、算法分类
算法是一门古老且庞大的学科,随着历史的发展,演化出多种多样的算法。按照不同的应用和特性,算法可以分为不同的类别。
1、按照应用来分类
按照算法的应用领域,即解决的问题,算法可以分为基本算法、数据结构相关的算法、几何算法、图论算法、规划算法、数值算法、数值分析算法、加密/解密算法、排序算法、查找算法、并行算法和数论算法等。
2、按照确定性来分类
按照算法结果的确定性来分类,算法可以分为确定性算法和非确定性算法。
确定性算法:这类算法在有限的时间内完成计算,得到的结果是唯一的,且经常取决于输入值。
非确定性算法:这类算法在有限的时间内完成计算,单是得到的结果往往不是唯一的,即存在多值性。
3、按照算法的思路来分类
按照算法的思路来分类,算法可以分为递推算法、递归算法、穷举算法、贪婪算法、分治算法、动态规划算法和迭代算法等多种算法。
三、算法与数据结构的关系
数据结构是数据的组织形式,可以用来表征特定的对象数据。在计算机程序设置中,操作的对象是各式各样的数据,这些数据往往拥有不同的数据结构,如数组、结构体、联合、指针和链表等。因为不同的数据结构所采用的处理方法不同,计算的复杂度也不同,因材算法往往依赖于某种数据结构。也就是说,数据结构的算法实现的基础。(程序=数据结构+算法)
四、流程图表示
流程图是一种图形表示算法流程的方法,其由一些图框和流程线组成。其中,图框标识各种操作的类型,图框中的文字和符号标识该操作的内容,流程线表示操作的先后次序。图框如下:
在实际使用中,一般采用如下三种流程结构。
顺序结构
顺序结构是最简单 的一种流程结构,简单的一个接着一个的进行处理,一般来说,顺序结构数和于简单的算法。
分支结构
分支结构常用语根据某个条件来决定算法的走向,如下所示。这里首先判断条件P,如果P成立,则执行B;否者执行A,然后在继续下面的算法。分支结构有時也称为条件结构。
循环结构
循环结构常用于需要反复执行的算法操作,按照循环的方式,可以分为当型循环结构和直到型循环结构。区别如下:
当型循环结构先对条件进行判断,然后再执行,一般采用while语句来实现。
直到循环结构先执行,然后在对条件进行判断,一般采用until、do...while语句来实现。
注:无论当型循环结构还是直到型循环结构,都需要进行合理的处理,以保证能够跳出循环;否则构成死循环是没有任何意义的。
一般来说,采用上述三种流程结构,可以完成所有的算法任务。通过合理安排流程结构,可以构成结构化的程序,这样便于算法程序的开发和交流。
五、算法的性能评价
算法其实就是解决问题的一种方法,一个问题的解决往往可以采用多种方法,但每种方法所用的时间和得到的效果往往是不一样的。算法的一个重要任务便是找到合适的、效率最高的解决问题的方法,即最好的算法。从理论上来讲,这就需要对算法的性能有一个合理的评论。一个算法的优劣往往通过算法复杂度来衡量,算法复杂度包括时间复杂度和空间复杂度两个方面。
1、时间复杂度
时间复杂度即通常所说的算法执行所需要耗费的时间,时间越短,算法越好。一个算法执行的时间往往无法精确估计,通常需要在实际的计算机中运行才能够知道。但是,也可以对算法的代码进行估计,而得到算法的时间复杂度。
2、空间复杂度
空间复杂度是指算法程序在计算机中执行所消耗的存储空间。空间复杂度可以分为如下两个方面。
1)程序保存所需要的存储空间,即程序大小。
2) 程序在执行中所需要小号的存储空间资源,如程序在执行过程中的中间变量等。
一般来说,程序的大小越小,执行过程中消耗的资源越少,这对程序就越好。
六、编程实例
1、使用while循环来计算1+2+3+....+100的值
public static void main(String[] args) {
/**
* 使用while循环来计算1+2+3+....+100的值
*/
int current= 1;//从1开始累加
int total = 0;//累加数
while (current<=100){
total+=current;
current++;
}
System.out.println(total);
}
效果如下:
5050
2、将ASCII码位于32~126之间的95个字符显示在屏幕上,为了美观,要求小于100的码值前填充一个0,每行打印8个字符。
public static void main(String[] args) {
/**
* 将ASCII码位于32~126之间的95个字符显示在屏幕上,为了美观,要求小于100的码值前填充一个0,每行打印8个字符。
*/
String temp = "";
for (int i = 32; i <= 126; i++) {
temp = i<100?("0"+i):(i+"");
System.out.print(temp+ "=" +(char) i+" ");
if ((i-31)%8 ==0){
System.out.println("\n");
}
}
效果如下:
032= 033=! 034=" 035=# 036=$ 037=% 038=& 039='
040=( 041=) 042=* 043=+ 044=, 045=- 046=. 047=/
048=0 049=1 050=2 051=3 052=4 053=5 054=6 055=7
056=8 057=9 058=: 059=; 060=< 061== 062=> 063=?
064=@ 065=A 066=B 067=C 068=D 069=E 070=F 071=G
072=H 073=I 074=J 075=K 076=L 077=M 078=N 079=O
080=P 081=Q 082=R 083=S 084=T 085=U 086=V 087=W
088=X 089=Y 090=Z 091=[ 092=\ 093=] 094=^ 095=_
096=` 097=a 098=b 099=c 100=d 101=e 102=f 103=g
104=h 105=i 106=j 107=k 108=l 109=m 110=n 111=o
112=p 113=q 114=r 115=s 116=t 117=u 118=v 119=w
120=x 121=y 122=z 123={ 124=| 125=} 126=~
3、使用for循环的嵌套,打印出九九乘法表
public static void main(String[] args) {
/**
* 使用for循环的嵌套,打印出九九乘法表
*/
for (int i = 1; i <= 9 ; i++) {
for (int j = 1; j <= i ; j++) {
System.out.print(j+"*"+i+"="+i*j+"\t");
}
System.out.println("");
}
}
效果如下:
1*1=1
1*2=22*2=4
1*3=32*3=63*3=9
1*4=42*4=83*4=124*4=16
1*5=52*5=103*5=154*5=205*5=25
1*6=62*6=123*6=184*6=245*6=306*6=36
1*7=72*7=143*7=214*7=285*7=356*7=427*7=49
1*8=82*8=163*8=244*8=325*8=406*8=487*8=568*8=64
1*9=92*9=183*9=274*9=365*9=456*9=547*9=638*9=729*9=81