[算法] - 入门
Posted gwyy
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[算法] - 入门相关的知识,希望对你有一定的参考价值。
序
这一篇文章是算法专栏第一篇文章。算法这个栏目会连载常用的算法(代码为Java),欢迎大家给我留言讨论。
1.什么是算法
1.1 算法定义
通俗的讲,算法是对问题求解过程的一种描述,是为解决一类问题给出一个确定的,有限的操作序列。曾经获得图灵奖的著名计算机科学家 D.Knuth 对算法做过一个为学术界广泛接受的描述性定义: 一个算法(angorithm)就是一个有穷规则的集合,其规则确定了一个解决某一特定问题的操作序列,算法的规则必须满足5下特征:
有穷性 --- 算法必须在执行有穷步骤后结束
确定性 --- 算法的每一个步骤必须是确切定义的
输入 --- 算法有零个或者多个输入
输出 --- 算法有一个或者多个输出,与输入有某种特定关系
可行性 --- 算法中有待执行的操作必须是相当基本的。即是说,他们原则上都是能精确的进行的,而且用笔和纸做有穷次就可以完成的
有穷性 和 可行性 是算法最重要的两个特征
1.2 算法的描述
算法可以用文字、高级程序设计语言或类似于高级程序设计语言的伪代码描述,此时,算法是由语义明确的操作步骤组成的有限序列。它精确的指出怎样从给定的输入信息得到要求的输出信息。
例如:在学生信息表中,按照姓名进行顺序查找(sequential search) 的算法思路为:对于给定值k 从线性表的一端开始,以此比较每个元素的姓名栏,如果存在姓名与k元素相同的数据,则查找成功,否则查找失败,这种方法是可行的,但是查找范围大,耗时长,查找不成功时,需要比较表中所有数据。
1.3 算法与数据结构
算法是建立在数据的逻辑结构和存储结构上的,数据结构和算法之间存在着本质的联系,失去一方,另一方就没有意义,在研究一个数据结构时,总是离不开对这个数据结构进行的各种操作。而且只有通过对这些操作的算法研究,才能更清楚的理解这中数据结构的意义和作用,反过来 在研究一种算法的时候,也总是自然地联系到这种算法建立在什么数据结构上。
1.对于同样的逻辑结构和存储结果,根据业务不同,可能会采用不同的算法。
2.同样的数据结构,不同的存储结构,则采用的算法必然不同。
存储结构不同的线性表其排序算法必然不同,例如 冒泡排序, 折半插入排序等,适用于顺序存储的数据结构,而不能用于链式存储的线性表,适用于链式存储的线性表的算法有 直接插入算法,简单选择排序等。
1.4算法与程序
算法使用抽象的语言描述解决的问题的每一步的操作,程序是计算机能够理解执行的指令序列,其中指令既可以是机器指令,汇编指令,也可以是高级语言的语句指令,通常一个程序实现一个算法,算法和程序的区别是:算法的执行是有穷的,而程序的执行可以是无限的,例如操作系统 只要系统不破坏 操作系统可以一直执行
2.算法的设计
2.1算法设计目标
算法设计应该满足以下5个目标:
正确性 --- 算法应该确切的满足具体问题的需求,这是算法设计的基本目标
可读性 --- 算法的可读性有利于人对算法的理解,这既有利于程序的调试和维护,也有利于算法的交流和移植,算法可读性注意体现在两方面,一是类名方法名 要见名知意,二是要有足够的注释
健壮性 --- 输入非法数据时,算法要能做出适当的处理,而不是产生不可预估的错误
高时间效率--- 算法时间效率指算法的执行时间,执行时间短的算法称为高时间效率算法
高空间效率--- 算法在执行时一般要求额外的内存空间,内存要求低的算法称为高空间效率算法
对于同一个问题,如果有很多种算法,应该尽量选择 高时间效率和高空间效率算法,算法的高事件效率和高空间效率一般是矛盾的,优先选择高时间效率
2.2 算法的分析 - 时间复杂度
算法执行时间等于所有语句执行时间总和,是算法所处理的数据个数n的函数,表示为 O(f(n)) O(f(n))称为该算法的时间复杂度(time complexity)O(1) 表示时间是个常数,不依赖于n O(n)表示时间与n成正比,是线性关系。O(n^2) 、O(n^3) 和 O(n^n) 分别称为平方阶,立方阶,指数阶,O(log2n) 为对数阶。
通常用算法时间复杂度来表示算法的时间效率,若2个算法执行时间分别是 O(1) 和 O(n) 当n充分大时,显然O(1) 执行的时间更少, 同样 O(n) 和 O(log2n) 相比较时,当N充分大时,因为log2n值比n小,则 O(log2n)所对应的算法要快的多。
下面我用详细的例子个大家演示:
首先是 O(1) 的算法,一个简单的语句算法复杂度就是 O(1),该语句执行时间是个常量。
sum=1
一个循环的时间复杂度是 O(n),for循环执行了n次 其中循环体内语句的执行了一次,时间是个常量 可以忽略不计,所以for循环时间复杂度是 O(n)
int n=0,sum=0; for (int i=0;i<n;i++) { sum+n; }
时间复杂度 O(n^2) 的二重循环, 外层循环执行了n次,每执行一次外层循环,内层循环就执行n此,所以二重循环的循环体语句执行了n*n次,
int n=0,sum=0; for (int i=0;i<n;i++) { for(j=0;j<n;j++) { System.out.println("hello liangtian"+i*j); } }
这种 外层循环执行了 n次 内层循环执行了 i次 也是 O(n^2)
int n=0,sum=0; for (int i=0;i<n;i++) { for(j=0;j<i;j++) { System.out.println("hello liangtian"+i*j); } }
时间复杂度为 O(nlog2n),外层循环执行了 log2n次外层循环没执行一次 i就乘以2,直到k>n 内层循环执行次数是n
int n=0,sum=0; for (int i=0;i<n;i*=2) { for(j=0;j<n;j++) { System.out.println("hello liangtian"+i*j); } }
时间复杂度为 O(n) 的二重循环, 外层循环执行 log2n 内层循环执行 i次 随着外层循环的增长而成倍增长,
int n=0,sum=0; for (int i=0;i<n;i*=2) { for(j=0;j<i;j++) { System.out.println("hello liangtian"+i*j); } }
时间复杂度表:
2.3 算法的分析 算法空间复杂度
与算法的时间复杂度类似,算法在执行时要求的额外内存空间称为算法的空间复杂度。
以上是关于[算法] - 入门的主要内容,如果未能解决你的问题,请参考以下文章
有人可以解释啥是 SVN 平分算法吗?理论上和通过代码片段[重复]