在谈算法之前,我们先来谈几个概念:
什么是算法
算法是在解决特定问题时,给出的步骤的描述,在计算机中表现为指令的有限序列,并且每条指令表示一个或者多个步骤c语言语法简单,强调数据结构,非常适合算法和数据结构描述。此外,作者还用cygwin64安装了gcc-core、gcc-g和make。具体安装方法请百度安装。
比如下面这段代码,作者用C/C语言编写的代码,
# include estio . h/* * *累加到给定的自然数n* @param [int] n自然数n* @return返回从1到n的自然数之和*/int add _ to _ number(int n){ int sum=0;int I=0;for(I=1;I=n;I){ sum=I;}返回总和;}int main(int args,char * argv){ int n=100;int sum=0;sum=add _ to _ number(n);printf(' 1到%d的和是%d ',n,sum);返回0;}上面简单的函数就是给一个自然数n,返回从1到n的累加和,这是一个算法。在函数体中清楚地描述了步骤,计算机根据这些指令操作,直到返回一个和。
编译运行:
$ gcc -o示例/simple.c -o示例/simple
运行结果
算法特性
输入和输出有一个输入或零个输入,但必须有一个输出,可以是简单的打印例如:
/* * *简单调试和打印方法*/void debug(char * msg){ # ifdef debug printf('[% s][% d]% s ',_ _ file _ _,_ _ line _ _,msg);#endif}不确定性是指在执行有限数量的步骤后,获得一个结果。这个有限的步骤可能需要几毫秒或几天后,但它不能无限期地进行下去。例如,我们通常启动一个web服务,并且我们总是在启动后监听客户端调用。
确定性值的步骤必须在正确的方向上确定和执行,编程是在可控的方向上进行的,因此程序的正确性无法控制,这意味着需要实践。
可行性算法的每一步都必须可行。算法最可恨的是数据类型的转换。如果不小心,Java抛出Null异常,C抛出Segment错误。虽然Python很少报告这个异常,但是会出现包括Attr和List在内的异常。
我们写算法的时候,首先要设计数据结构,一定要搞清楚我用的是什么数据类型,做的是什么转换,最后变成什么数据类型。我们必须对此了如指掌。C是基础语言,所以我们将用C来编写和解释代码。
检验算法的标准
正确性意味着输入指定的参数并输出正确和明确的数据。我们可以测试输入参数:一段算法要求有很高的可读性,我们在项目工程上,更需要可读性,在日常的代码维护中很重要,必要的时候需要加上注释,不要出现当时只有我和上帝能懂,一段时间后只有上帝能读懂的情况,[我想静静][我想静静][我想静静],例如:
// 这段算法的意义是什么++c;c << 1;
- 健壮性
在编写代码之前要考虑可能出现的异常,也就是在风险管理上,要有风险清单,遇到哪个风险触发对应的风险管理,对于未知的风险,我们可能就要通过测试去进一步完善了,代码健壮性在一步一步地完善之中。
- 速度快和存储低
这里给出时间复杂度大O表示法,记为O(f(n)),其中f(n)是循环变量n的函数,推导大O的方法很简单:
- 用常数1取代运行时间中的所有加法常数。
- 在修改后的运行次数函数中,只保留最高阶项。
- 如果最高阶项存在且不是1,则去除与这个项相乘的常数。
举个栗子:
一个算法的时间函数为 f(n) = 1/2 * n^3 + n + 10000
- f(n) = 1/2 * n^3 + n + 1
- f(n) = 1/2 *n^3 + 1
- f(n) = n ^ 3 + 1
最终算法的时间复杂度为O(n^3),因为1这个常数级复杂度跟n^3来比太微乎极微了,可以省去。
平方阶
int i, j;for (i = 0; i < n; i++){for (j = 0; j < n; j++) { .... }}
时间复杂度为O(n^2),一般的幂次方函数的表现形式为嵌套多层循环,每次循环都是从1到n。
对数阶
int i = 1;while(i < n){i = i * 2;}
每次循环i 都乘以2,直到x次,到达n,2^x = n,求x就成为log2n,以2为低n的对数。
指数阶
/*** 斐波那契数列第n项* @param [int] n 第n项* @return 返回第n的数*/int fab(int n){if (n == 0 || n == 1) { return n } return fab(n-1, n-2)}
每一项都是由它的后两项确定的,直到递推到n=1或者n=0的时候,才会返回,一分为2,2再分为4,...,也就是2^n。
讨论算法,应该考虑最好情况,最坏情况和平均情况,这是非常重要的。
下面给出时间复杂度对比图,比较直观:

在我们编写算法的过程中,是一个辩证的过程,像哲学中的否定之否定规律,不断的否定我们写过的算法,诞生的新算法更加的符合我们的预期。
算法用到了数学的一些知识,只是达到了应用的层面,后面的算法还会用到矩阵、极限、微积分等,大家不必惊慌,我会举例说明,大家不是考研,不需要研究很深入,但了解背后的数学知识很有必要。
下节会联合数据结构将算法,希望大家支持哦[谢谢][谢谢][谢谢]。
参考《大话数据结构》