算法:算法是解决特定问题求解步骤的描述,在计算机中表现为指令的有限序列,并且每条指令表示一个或多个操作。
数据结构和算法的关系是相互依赖,不可分割的。
算法是对一些思想步骤的描述,不是具体的代码实现,根据不同的问题要具体分析,就事论事。我们应该把算法当作工具,熟练掌握它们,灵活运用它们。
对比记忆算法的特性和算法设计的要求
- 算法的特性:有穷性,可行性,确定性,输入,输出。
- 有穷性:在执行有限步骤后可以达到目的,不会出现无限循环或不现实运行时间。
- 可行性:每个步骤要能够实行。
- 确定性:每个步骤都是准确无歧义的,对应结果唯一。
- 输入,输出:可以没有输入,但至少要有一个输出。
- 算法设计的要求:正确性,可读性,健壮性,高效率和低储存量需求。
- 正确性:这是最基本的要求,语法上,对于合法输入数据的处理得到正确答案,对于非法数据有效说明,程序能够满足所有数据情况。
- 可读性:算法应该易于他人和自己理解,不能写的晦涩难懂。因为算法设计的另一大目的是为了便于阅读,理解和交流。(可读性是算法(也包括实现它的代码)好坏的很重要的标志)。
- 健壮性:考虑要全面完善,对于非法的数据输入不应该得到一个莫名其妙的结果,要进行适当的处理,让运行者明白输入的数据是否出现了问题。简而言之就是对输入数据不合法的情况做适当的处理。
- 高效率和储存量低:很好理解,即在前面3点的前提下,运行时间短,程序占用内存小。无论做什么事情,人们总是会在能达到目的的基础上再追求高效率,即不断优化。为测算效率,由此引出两个关键名词:时间复杂度和空间复杂度。(我们可以用空间换时间,或者时间换空间,我们要就具体情况选择不同方法)。(tip:当不用限定词地使用“复杂度”时,通常都是指时间复杂度)
事前分析估算法
在这之前我们要理解一个概念:函数的渐近增长。即给定两个函数f(n)和g(n),如果存在一个整数N,使得对于所有的n>N,f(n)总是比g(n)大,那么,我们说f( n)的增长渐近快于g(n)。通过对比算法的关键执行次数函数的监禁增长性,我们可以得出:某个算法,随着n的变大,它会越来越优于另一算法,或者越来越差于另一算法。
在写程序之前,想好了思路之后要先估算效率,可以减少很多不必要的麻烦。
首先给出时间复杂度的概念:
n称为问题的规模,当n不断变化时,时间频度T(n)也会不断变化。但有时我们想知道它变化时呈现什么规律。为此,我们引入时间复杂度概念。 一般情况下,算法中基本操作重复执行的次数是问题规模n的某个函数,用T(n)表示,若有某个辅助函数f(n),使得当n趋近于无穷大时,T(n)/f(n)的极限值为不等于零的常数,则称f(n)是T(n)的同数量级函数。记作T(n)=O(f(n)),称O(f(n)) 为算法的渐进时间复杂度,简称时间复杂度。
我们要通过数学的思想先得到运行次数关于n的表达式。
对该表达式的处理用到的是一下方法。
估算时间复杂度的方法:大O记法。
(1)用常数1取代运行时间中的所有加法常数。
(2)在修改后的运行次数函数中,只保留最高阶项。
(3)如果最高阶项存在且其系数不为1,则去除其系数,得到的结果就是大O阶。
常见的时间复杂度有:常数阶,线性阶,平方阶,立方阶,对数阶,nlogn阶,指数阶等。
它们的费时关系为:
O(1)<O(logn)<O(n)<O(nlogn)<O(n^2)<O(2^n)<O(!n)<O(n^n)
最坏情况与平均情况
最坏情况可以理解为是一种保证,运行时间不会再多于最坏情况了。而平均情况是运行时间的期望值,是我们所希望看到的运行时间。
-----------------------------------------------------------------end-----------------------------------------------------------
2022.1.9