一、什么是算法
程序=数据结构+算法
数据结构是程序的框架,算法是程序的灵魂。
二、算法的复杂性
例、写一个算法,求以下序列之和:
-1,1,-1,1,…,(-1)^n
方法一:(for循环)
int sum(int n)
{
int sum=0;
for(int i=1;i<=n;i++)
sum+=pow(-1,i);//表示(-1)^i
return sum;
}
方法二:
int sum(int n)
{
int sum=0;
if(sum%2==0)
sum=1;
else
sum==-1;
return sum;
}
算法可以用自然语言,程序设计语言描述,也可以用流程图,框图来表示,一般为了更清楚地说明算法的本质,一般用“伪代码”来表示。
算法具有以下特性:
- 有穷性:算法有若干条指令组成的有穷序列,总是在执行若干次后结束,不可能永不停止。
- 确定性:每条语句都有确定的含义,无歧义。
- 可行性:算法在当前环境条件下可以通过有限次运算来实现。
- 输入/输出:有零个或多个输入以及一个或多个输出。
三、好算法的标准
- 正确性:能满足具体问题的需要,程序运行正常,无语法错误,能通过软件调试。
- 易读性:算法遵循标识符命名规则,注释语句恰当,方便阅读和调试。
- 健壮性:算法对非法数据有较好的操作反应和处理。
- 高效性:消耗的时间短。
- 低存储性:所需存储空间小。
四、时间复杂度
算法运行需要的时间。
算法的运行时间主要取决于最高项,小项和常数项忽略不计。
五、空间复杂度
算法占用的空间大小。
苏研发占用的空间包括:
输入/输出数据;
算法本身;
额外需要的辅助空间。
注意:在递归算法中,每一次递推都需要一个宅空间来保存,在分析算法的空间复杂度时,需要计算递归栈的辅助空间。
六、递归算法的空间复杂度
例:计算n的阶乘
int fac(int n)
{
if(n==0||n==1)
return 1;
else
return n*fac(n-1);
}
上述例子为典型的递归调用问题,递归包括递归和回归。
在计算机内部,使用一种称为“栈”的数据结构来实现上述过程。
栈每次从顶端放进去一个,拿出来的时候只能从顶端拿出来一个,不允许从中间插入或抽取,因此称为“后进先出”栈。
若用T(n)表示fac(n)的时间复杂度,可以表示为
T(n)=T(n-1)+1
=T(n-2)+1+1
…
=T(1)+1+…+1+1
=n
例子:一棋盘的麦子
在印度有一个古老的传说:舍罕王打算奖赏国际象棋的发明人——宰相:西萨·班·达依尔。国王问他想要什么,他对国王说:“陛下,请您在这张棋盘的第1个小格里,赏给我1粒麦子,在第2个小格里给2粒,第3小格给4粒,以后每一小格都比前一小格加一倍。请您把这样摆满棋盘上所有的64格的麦粒,都赏给您的仆人吧!”国王觉得这要求太容易满足了,就命令给他这些麦粒。当人们把一袋一袋的麦子搬来开始计数时,国王才发现:就是把全印度甚至全世界的麦粒全拿来,也满足不了那位宰相的要求。 那么,宰相要求得到的麦粒到底有多少呢?
分析:
64个格子麦粒的放置:S=1+2^1+ 2^2+ 2^3+…+ 2^63
常见算法时间复杂度有以下几类:
- 常数阶 O(1)
- 多项式阶 O(n),O(n^2), O(n^3)
- 指数阶 O(2^n),O(n!), O(n^n)
- 对数阶 O(logn),O(nlogn)