1、遞推算法
遞推算法是一種用若干步可重複的簡運算(規律)來描述複雜問題的方法。函數
遞推是序列計算機中的一種經常使用算法。它是按照必定的規律來計算序列中的每一個項,一般是經過計算機前面的一些項來得出序列中的指定項的值。其思想是把一個複雜的龐大的計算過程轉化爲簡單過程的屢次重複,該算法利用了計算機速度快和不知疲倦的機器特色。spa
例1:植樹節那天,有五位同窗參加了植樹活動,他們完成植樹的棵樹都不相同。問第一位同窗植了多少棵時,他指着旁邊的第二位同窗說比他多植了兩棵;追問第二位同窗,他又說比第三位同窗多植了兩棵;... 如此,都說比另外一位同窗多植兩棵。最後問到第五位同窗時,他說本身植了10棵。到底第一位同窗植了多少棵樹?設計
分析:設第一位同窗植樹的棵樹爲a1,欲求a1,需從第五位同窗植樹的棵數a5入手,根據「多兩棵」這個規律,按照必定順序逐步進行推算:
(1) a5=10;
(2) a4=a5+2=12;
(3) a3=a4+2=14;
(4) a2=a3+2=16;
(5) a1=a2+2=18;blog
var
i,a:byte;
begin
a:=10;
for i:=1 to 4 do a:=a+2;
writeln('The Num is',a);
end.遞歸
本程序的遞推運算可用下圖示表示:
初始值a:=10-----i=1,a=a+2(12)-----i=2,a=a+2(14)------i=3,a=a+2(16)-----i=4,a=a+2(18)----輸出a值數學
例2:十本不一樣的書放在書架上,現從新擺放,使每本書都不在原來放的位置,有幾種擺法?it
分析:當n個元素放在n個編號位置,元素編號與位置編號各不對應的方法數用M(n)表示,那麼M(n-1)就表示n-1個編號元素放在n-1個編號位置且各不對應的方法數,其它類推。io
第一步,把第n個元素放在除n之外的某一個位置,好比位置k,一共有n-1種方法
第二步,放編號爲k的元素,這時有兩種狀況:
一、把它放到位置n,那麼對於剩下的n-2個元素,就有M(n-2)種方法
二、不把它放到位置n,這時對於這n-1個元素有M(n-1)種方法function
綜上獲得:
M(n)=(n-1)*[M(n-2)+M(n-1)] (n>=3)
var
n,i:byte;
a,b,c:longint;
begin
readln(n);
case n of
1: writeln(0);
2: writeln(1);
else begin
a:=0;b:=1;
for i:=3 to n do begin
c:=(i-1)*(a+b);
a:=b;b:=c;
end;
writeln(c);
end;
end;
end.
遞推算法以初始(起點)值爲基礎,用相同的運算規律,逐次重複運算,直至運算結束。這種從「起點」重複相同的方法直至到達必定「邊界」,猶如單向運動,用循環能夠實現。遞推的本質是按規律逐次推出(計算)先一步的結果。
2、遞歸
若是函數體或過程體中出現調用其自身的語句,稱爲遞歸調用。這樣的函數或過程稱爲遞歸函數或遞歸過程。
例3:設計一個計算n!的遞歸程序
根據數學含義,n!可由下面的公式表示:
n!=1 當n=0時
n!=n*(n-1)! 當n>0時
根據以上公式推理,爲了求n!能夠先求出(n-1)!,爲了求(n-1)!又能夠先求出(n-2)!……,如此遞推,直到n=0。因爲n=0時已定義爲1,再由0!=1又一步步反向推回,求出1!、2!……最終獲得n!
var
n:integer;
function fct(t:integer):integer;
begin
if t=0 then fct:=1
else fct:=t*fct(t-1);
end;
begin
readln(n);
writeln(n,'!=',fct(n));
end.
例4:漢諾(hanoi)塔問題。給定三根杆A、B、C和大小不一樣的幾個盤子,這些盤子按尺寸遞減順序套在A杆上,如圖。咱們的任務是把這些盤子從A杆移到C杆且保持原來堆放順序;在實現任務時,規定每次只能移動一個盤子,不容許大的盤子放在小的盤子上面,B杆能夠做爲輔助存放杆,求出每一步應該如何移動。
題目要求將n個盤子由A杆移到C杆可用一樣的方法:
一、先(遞歸地)將A杆上面的n-1個盤子移到B杆(藉助C杆)
二、而後把A杆上惟一的一個盤子移到C杆
三、再把B杆上的n-1個盤子(遞歸地)移到C杆(藉助A杆)
var
n:integer;
procedure move(n:integer;a,b,c:char);
begin
if n=1 then writeln(a,'--->',c)
else begin
move(n-1,a,c,b);
writeln(a,'--->',c);
move(n-1,b,a,c);
end;
end;
begin
readln(n);
move(n,'A','B','C');
end.
遞歸結構的程序具備結構清晰,容易閱讀和理解的優勢,寫出的程序較簡短,但在處理遞歸問題中,須要保留每次遞歸調用時的參數和局部變量,這樣就佔用大量的存儲空間和花費較多的機器時間,效率較低。
用遞歸過程或函數解決問題時應注意:
一、求解的問題是否符合遞歸的描述,要解決的問題是否能夠化爲與原問題相同的子問題
二、過程體或函數體中必須有遞歸結束的條件,這個條件就是遞歸邊界
3、做業
一、zerojudge:a21六、a04二、b12七、a51九、d580、d2十二、d810
二、用遞歸方法求兩個正整數的最大公約數
三、讀入一個任意位數的正整數,按顛倒過來的順序將其輸出(利用遞歸過程)
四、從鍵盤輸入任意長度的一串字符,其中包括數字和字母,並以星號「*」結束。利用遞歸的方法將這串字符中的數字字符按相反的次序個輸出。例如:輸入Delphi6TP70Ada586*,輸出爲685076。