算法设计与分析
第一章、算法概述
1。用计算机求解问题的步骤
答:1、问题分析
2、数学模型建立
3、算法设计与选择
4、算法表示
5、算法分析
6、算法实现
7、程序测试及调试
8、结果整理文档编制
2、算法的定义
答:算法是指在解决问题时,按照某种机械步骤一定可以得到问题结果的处理过程
所谓机械步骤是指,算法中有待执行的运算和操作,必须是相当基本的
3、算法的三要素
答:算法由操作、控制结构、数据结构3要素组成
操作:算术运算、关系运算、逻辑运算、数据传送
控制结构:顺序结构、选择结构、循环结构(递归机制)
数据结构:数据间的逻辑关系、数据的存储方式几处理方式就是数据的数据结构
4、算法的基本性质
答:目的性、分布性、有序性、有限性、操作性
5、算法的基本特征
答:有穷性、确定性、可行性、算法有零个或多个的输入、算法有一个或多个的输出
6、算法的质量指标 ★★
答:正确性、可读性、稳健性、高效率与低存储量需求
7、结构化方法
答:自顶向下、逐步求精、模块化
【例】求两个正整数的最大公约数
int main(void)
{
int a, b, t, i;
scanf("请输入两个数%d,%d", &a, &b);
t = 1;
for (i = 2; i <= a || i <= b; i = i + 1)
while (a % i == 0 || b % i == 0)
{
t = t * i;
a = a / i;
b = b / i;
}
printf("%d,%d maximal common divisor is %d", a, b, t);
}
第二章、算法分析基础
1、算法的分析和评价 ★
答:对于算法的分析和评价,一般考虑正确性、可维护性、可读性、运算量、占用存储控件等因素,其中评价算法的3条重要指标是:
(1)算法实现所耗费的时间;
(2)算法实现所耗费的存储空间,其中主要考虑辅助存储空间;
(3)算法应易于理解、易于编码、易于调试等;
2、与算法执行时间相关的因素
答:
问题中数据存储的数据结构。
算法采用的数学模型
算法设计的策略
问题的规模
实现算法的程序设计语言
编译算法产生的机器代码的质量
计算机执行指令的速度
3、频度:语句的频度是指该语句重复执行的次数
4、算法的储存量包括
答:
输入数据所占空间;
算法(程序)本身所占空间;
辅助变量所占空间。
第三章、算法基本工具和优化技巧
1、递归设计要点:
答:
分析问题、寻找递归关系:找出大规模问题与小规模问题的关系,这样通过递归使问题的规模逐渐变小。
设置边界、控制递归:找出停止条件,即算法可解的最小规模问题。
设计函数、确定参数:和其他算法模块一样设计函数体中的操作及相关参数。
2、什么是数学模型:
答:数学模型是利用数学语言(符号、式子与图像)模拟现实的模型。把现实模型抽象、简化为某种数学结构是数学模型的基本特征。
【例1】求1/1!-1/3!+1/5!-1/7!+...+(-1)n+1/(an-1)!
main()
{
int i,n,j,sign=1;
float s,t=1;
input(n);
s=1;
for(i=2;i<=n;i=i+1)
{
t=1;
for(j=1;j<=2*2-1;j=j+1)
t=t*j;
sign=1;
for(j=1;j<=i+1;j=j+1)
sign=sign*(-1);
s=s+sign/t;
}
print("Sum=",s);
}
【例2】编写算法:打印具有下面规律的图形。
1
5 2
8 6 3
10 9 7 4
main ()
{
int i,j,a[100][100],n,k;
input(n);
k=1;
for(i=1;i<=n;i=i+1)
for(j=1;j<=n+1-i;j=j+1)
{
a[i-1+j][j]=k;
k=k+1;
}
for(i=1;i<=n;i=i+1)
{
print('换行符');
for(j=1;j<=i;j+j+1)
print(a[i][j]);
}
}
【例3】任给十进制的正整数,请从低位到高位逐位输出各数字。
循环算法:
main()
{
int n;
input(n);
while (n>=10)
{
print(n mod 10);
n=n\10;
}
print(n);
}
递归算法:
main()
{
int n;
input (n);
f(n);
}
f(int n)
{
if(n<10)
print(n);
else
{
print(n mod 10);
f(n\10);
}
}
【例4】开灯问题
main()
{
int n,a[1000],i,k;
print("input a number");
input(n);
for (i=1;i<=n;i=i+1)
a[i]=0;
for (i=2;i<=n;i=i+1)
{
k=1;
while (i*k<=n)
{
a[i*k]=1-a[i*k];
k=k+1;
}
}
for (i=1;i<=n;i=i+1)
if (a[i]=1)
print(i);
}
【例5】抓小偷问题
main()
{
int x;
for(x=1;x<=4;x=x+1)
if((x<>1)+(x=3)+(x=4)+(x<>4)=3)
print(chr(64+x),"is a thief");
}
【例6】编写算法对输入的整数进行判断能否被3,5,7整除,并输出以下信息
main()
{
long n;
int k;
print("please enter a number:");
input(n);
k=(n mod 3=0)+(n mod 5=0)+(n mod 7=0)
switch(k)
{
case 3:print('all');break;
case 2:print('two');break;
case 1:print('one');break;
case 0:print('none');break;
}
}
第四章、基本的算法策略
1、迭代算法
答:迭代法也称“辗转法”,是一种不断用变量的旧值递推出新值的解决问题的方法。(累加、累乘、阶乘)
2、推倒法
答:推倒法是对某些特殊问题所采用的违反通常习惯的,从后向前解问题的方法。
3、枚举法
答:枚举法(穷举法)是蛮力策略的一种表现形式,也是一种使用非常普遍的思维方法。它是根据问题中的条件将可能的情况一一列举出来,逐一尝试从中找出满足问题条件的解。
4、贪婪算法
答:贪婪法又叫登山法,他的根本思想是逐步到达山顶,即逐步获得最优解,是解决最优化问题时的一种简答但适用范围有限的策略。
5、设计动态规划算法的基本步骤
答:1、划分阶段 2、选择状态 3、确定决策并写出状态转移方程
实际应用中可以安装一下简化步骤设计:
(1)分析最优解的性质,并刻画其结构特征。
(2)递推定义最优值。
(3)已自底向上的方式或自顶向下的记忆化方法(备忘录法)计算出最优值。
(4)根据计算最优值时得到的信息,构造问题的最优解。
【例1】兔子繁殖问题(斐波那契数列)
算法1:
main(){ int i,a=1,b=1; print(a,b); for (i=1;i<=10;i=i+1) { c=a+b; print(c); a=b; b=c; }}
算法2:
main(){ int i,a=1,b=1; print(a,b); for (i=1;i<=4;i=i+1) { c=a+b; a=b+c; b=a+c; print(a,b,c); }}
算法3:
main(){ int i,a=1,b=1; print(a,b); for (i=1;i<=5;i=i+1) { a=a+b; b=a+b; print(a,b) }}
【例2】求两个整数的最大公约数(辗转相除法)
main(){ int a,b; input(a,b); if (b=0) { print("data error"); return; } else { c=a mod b; while c<>0 { a=b; b=c; c=a mod b; } } print(b);}
【例3】猴子吃桃问题
main(){ int i,a; a=1; for (i=9;i>=1;i=i-1) a=(a+1)*2; print(a);}
【例4】杨辉三角
main(){ int n,i,j,a[100]; input(n); print('1'); print('换行符'); a[1]=a[2]=1; print(a[1],a[2]); print('换行符'); for (i=3;i<=n;i=i+1) { a[1]=a[i]=1; for (j=i-1;j>1,j=j-1) a[j]=a[j]+a[j-i]; for (j=1;j<=i;j=j+1) print(a[j]); print('换行符'); }}
【例5】牛顿迭代法。
利用牛顿迭代法,求ax3+bx2+cx+d=0的根。
main(){ float a,b,c,d,fx; print('输入系数a,b,c,d:'); input(a,b,c,d); fx=f(a,b,c,d); print('方程的根为:',fx);}float f(a,b,c,d)float a,b,c,d;{ float x1=1,x0,f0,f1; do { x0=x1; f0=((a*x0+b)*x0+c)*x0+d; f1=(3*a*x0+2*b)*x0+c; x1=x0-f0/f1; } while (fabs(x1-x0)>=1e-4);return(x1);}
【例6】二分法求解方程f(x)=0的根
main(){ float x,x1=0,x2=2,f1,f2,f; print("input x1,x2(f(x1)*f(x2)<0)"); input(x1,x2); f1=x1*x1*x1/x2+2*x1*x1-8; f2=x2*x2*x2/x2+2*x2*x2-8; if (f1*f2>0) { print("Non root"); return; } do { x=(x1+x2)/2; f=x*x*x/2+2*x*x-8; if(f=0) break; if(f1*f>0.0) { x1=x; f1=f; } else x2=x; } while (fabs(f)>=1e-4); print('root=',x);}
【例7】金块问题
maxmin(float a[],int n){ max=a[1]; min=a[1]; for (i=2;i<=n;i=i+1) if(max<a[i]) max=a[i]; else if(min>a[i]) min=a[i];}