算法設計與分析
第一章、算法概述
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];}