當前位置:首頁 » 操作系統 » 遞歸演算法逸代

遞歸演算法逸代

發布時間: 2022-08-09 16:13:39

『壹』 c語言遞歸演算法

本人學c++,c的語法已經淡忘了,但是遞歸不管什麼語言都是一個原理
其實簡單一點來說就像數學裡面的數列的通項公式:
例如一個數列是2,4,6,8,10......
很容易就可以得到通項公式是a[n]=2*n n是大於0的整數
你肯定學過這個數列的另外一種表示方式就是: a[1]=2, a[n]=a[n-1]+2 n是大於1的整數
其實這就是一個遞歸的形式,只要你知道初始項的值,未知項和前幾項之間的關系就可以知道整個數列。
程序例子:比如你要得到第x項的值
普通循環:
for(int i=1; i<=n; i++)
if (i == x)
cout << 2*i; /*cout 相當於 c裡面的printf,就是輸出.*/
遞歸:
int a(int x) {
if (x = 1)
return 2; /* 第一項那肯定是2了,這個也是遞歸的終止條件! */
else return a(x-1)+2; /* 函數自身調用自身是遞歸的一個特色 */
比如x=4,那麼用數學表示就是a(4)=a(3)+2=(a(2)+2)+2=((a(1)+2)+2)+2
其實遞歸方法最接近自然,也是最好思考的一個方法,難點就是把對象建模成遞歸形式,但是好多問題本身就是以遞歸形式出現的。
普通遞歸就是數據結構上的堆棧,先進後出。
例如上面x=4,把a(4)放入棧底,然後放入a(3),然後a(2),a(1),a(1)的值已知,出棧,a(1)=2,a(2)出棧a(2)=a(1)+2=2+2=4,a(3)出棧a(3)=a(2)+2=(a(1)+2)+2=6,a(4)出棧a(4)=a(3)+2=(a(2)+2)+2=((a(1)+2)+2)+2=8
再比如樓上的階乘例子,當n=0 或 1時,0!=1,1!=1,這個是階乘的初始值,也是遞歸的終止條件。然後我們知道n!=n*(n-1)!,當n>1時,這樣我們又有了遞歸形式,又可以以遞歸演算法設計程序了。(樓上已給出譚老的程序,我就不寫了)。
我給出一種優化的遞歸演算法---尾遞歸。
從我給出的第一演算法可以看出,先進棧再出棧,遞歸的效率是很低的。速度上完全比不上迭代(循環)。但是尾遞歸引入了一個新的函數參數,用這個新的函數參數來記錄中間值.
普通遞歸階乘fac(x),就1個x而已,尾遞歸用2個參數fac(x,y),y存放階乘值。
所以譚老的程序就變成
// zysable's tail recursive algorithm of factorial.
int fac(int x, int y) {
if (x == 1)
return y;
else return fac(x-1, y*x);}
int ff(int x) {
if (x == 0)
return 1;
else return fac(x,1);}
對於這個程序我們先看函數ff,函數ff其實是對fac的一個封裝函數,純粹是為了輸入方便設計的,通過調用ff(x)來調用fac(x,1),這里常數1就是當x=1的時候階乘值了,我通過走一遍當x=3時的值即為3!來說明一下。
首先ff(3),x!=0,執行fac(3,1).第一次調用fac,x=3,y=1,x!=1,調用fac(x-1,y*x),新的x=2,y=3*1=3,這里可以看到,y已經累計了一次階乘值了,然後x還是!=1,繼續第三次調用fac(x-1,y*x),新的x=1,y=2*3=6,然後x=1了,返回y的值是6,也就是3!.你會發現這個遞歸更類似於迭代了。事實上我們用了y記錄了普通遞歸時候,出棧的乘積,所以減少了出棧後的步驟,而且現在世界上很多程序員都在倡議用尾遞歸取消循環,因為有些在很多解釋器上尾遞歸比迭代稍微效率一點.
基本所有普通遞歸的問題都可以用尾遞歸來解決。
一個問題以遞歸來解決重要的是你能抽象出問題的遞歸公式,只要遞歸公式有了,你就可以放心大膽的在程序中使用,另外一個重點就是遞歸的終止條件;
其實這個終止條件也是包含在遞歸公式裡面的,就是初始值的定義。英文叫define initial value. 用普通遞歸的時候不要刻意讓自己去人工追蹤程序,查看運行過程,有些時候你會發現你越看越不明白,只要遞歸公式轉化成程序語言正確了,結果必然是正確的。學遞歸的初學者總是想用追蹤程序運行來讓自己來了解遞歸,結果越弄越糊塗。
如果想很清楚的了解遞歸,有種計算機語言叫scheme,完全遞歸的語言,因為沒有循環語句和賦值語句。但是國內人知道的很少,大部分知道是的lisp。
好了,就給你說到這里了,希望你能學好遞歸。

PS:遞歸不要濫用,否則程序極其無效率,要用也用尾遞歸。by 一名在美國的中國程序員zysable。

『貳』 什麼叫遞歸法

1、遞歸演算法概念:

在函數或子過程的內部,直接或者間接地調用自己的演算法。

2、基本信息:

遞歸演算法是把問題轉化為規模縮小了的同類問題的子問題。然後遞歸調用函數或過程來表示問題的解。一個過程或函數直接或間接調用自己本身,這種過程或函數叫遞歸過程或函數。

『叄』 遞歸演算法的程序結構比迭代演算法的程序結構更為精煉,這個正確嗎,能不能解釋下

對,更精煉,比如說
求一個函數
f(n) = f(n-1) + 1; f(1) = 1;

寫遞歸就和這個函數的定義差不多,非常簡潔明了

int f(int n)
{
if (n==1)
return 1;
else return f(n-1);
}

『肆』 什麼是遞歸演算法有什麼作用

作者名:不詳 來源:網友提供 05年7月7日

無法貼圖 ,自己到 http://51zk.csai.cn/sjjg/NO00223.htm 看去吧

1、調用子程序的含義:
在過程和函數的學習中,我們知道調用子程序的一般形式是:主程序調用子程序A,子程序A調用子程序B,如圖如示,這個過程實際上是:

@當主程序執行到調用子程序A語句時,系統保存一些必要的現場數據,然後執行類似於BASIC語言的GOTO語句,跳轉到子程序A(為了說得簡單些,我這里忽略了參數傳遞這個過程)。
@當子程序A執行到調用子程序B語句時,系統作法如上,跳轉到子程序B。
@子程序B執行完所有語句後,跳轉回子程序A調用子程序B語句的下一條語句(我這又忽略了返回值處理)
@子程序A執行完後,跳轉回主程序調用子程序A語句的下一條語句
@主程序執行到結束。
做個比較:我在吃飯(執行主程序)吃到一半時,某人叫我(執行子程序A),話正說到一半,電話又響了起來(執行子程序B),我只要先接完電話,再和某人把話說完,最後把飯吃完(我這飯吃得也夠累的了J)。
2、認識遞歸函數
我們在高中時都學過數學歸納法,例:
求 n!
我們可以把n!這么定義

也就是說要求3!,我們必須先求出2!,要求2!,必須先求1!,要求1!,就必須先求0!,而0!=1,所以1!=0!*1=1,再進而求2!,3!。分別用函數表示,則如圖:

我們可以觀察到,除計算0!子程序外,其他的子程序基本相似,我們可以設計這么一個子程序:
int factorial(int i){
int res;
res=factorial(I-1)*i;
return res;
}
那麼當執行主程序語句s=factorial(3)時,就會執行factorial(3),但在執行factorial(3),又會調用factorial(2),這時大家要注意,factorial(3)和factorial(2)雖然是同一個代碼段,但在內存中它的數據區是兩份!而執行factorial(2)時又會調用factorial(1),執行factorial(1)時又會調用factorial(0),每調用一次factorial函數,它就會在內存中新增一個數據區,那麼這些復制了多份的函數大家可以把它看成是多個不同名的函數來理解;
但我們這個函數有點問題,在執行factorial(0)時,它又會調用factorial(-1)。。。造成死循環,也就是說,在factorial函數中,我們要在適當的時候保證不再調用該函數,也就是不執行res=factorial(I-1)*i;這條調用語句。所以函數要改成:
int factorial(int i){
int res;
if (I>0) res=factorial(I-1)*i; else res=1;
return res;
}
那麼求3!的實際執行過程如圖所示:

3、如何考慮用遞歸的方法來解決問題
例:求s=1+2+3+4+5+6+……+n
本來這個問題我們過去常用循環累加的方法。而這里如要用遞歸的方法,必須考慮兩點:
1) 能否把問題轉化成遞歸形式的描述;
2) 是否有遞歸結束的邊界條件。
設:函數s(n)=1+2+3+…+(n-1)+n
顯然遞歸的兩個條件都有了:
1) s(n) =s(n-1)+n
2) s(1)=1
所以源程序為:
int progression(int n){
int res;
if (n=1 )res=1 else res=progression(n-1)+n;
return res;
}
4、遞歸的應用
中序遍歷二叉樹
void inorder (BinTree T){
if (T){
inorder(T->lchild);
printf(「%c」,T->data);
inorder(T->rchild);
}
}
現假設樹如圖(為了講解方便,樹很簡單)

@執行第一次調用inorder1,T指向頂結點,T不為空,所以第二次調用inorder2;
@T指向頂結點的左子樹結點也就是B,不為空,所以第三次調用inorder3;
@T指向B結點的左子樹結點,為空,所以什麼都不執行,返回inorder2;
@列印B結點的DATA域值「b」;
@第四次調用inorder4,去訪問B子樹的右結點
@T指向B結點的右子樹結點,為空,所以什麼都不執行,返回inorder2;
@返回inorder1;
@列印A結點的DATA域值「a」;
@第五次調用inorder5,去訪問A子樹的右結點;
@T指向A結點的右子樹結點,為空,所以什麼都不執行,返回inorder1;
@inorder1執行完畢,返回。

『伍』 在c語言中遞歸和迭代有什麼區別和聯系各自的優缺點是什麼二者分別適合解決什

能力有限,僅知幾點
兩者都是重復某一操作直到滿足條件為止。
不同之處在於,遞歸是函數調用自身,而迭代是使用循環。
某些情況下遞歸更加簡單,可讀性更高,而用循環則十分復雜。如二分法,快速排序等。
遞歸很容易導致棧溢出,導致程序崩潰,而循環不會。
綜上所述,能用循環用循環,遞歸是萬不得已的手段。

『陸』 java中遞歸演算法是什麼怎麼算的

一、遞歸演算法基本思路:

Java遞歸演算法是基於Java語言實現的遞歸演算法。遞歸演算法是一種直接或者間接調用自身函數或者方法的演算法。遞歸演算法實質是把問題分解成規模縮小的同類問題的子問題,然後遞歸調用方法表示問題的解。遞歸往往能給我們帶來非常簡潔非常直觀的代碼形式,從而使我們的編碼大大簡化,然而遞歸的思維確實跟我們的常規思維相逆的,通常都是從上而下的思維問題,而遞歸趨勢從下往上的進行思維。

二、遞歸演算法解決問題的特點:

【1】遞歸就是方法里調用自身。

【2】在使用遞歸策略時,必須有一個明確的遞歸結束條件,稱為遞歸出口。

【3】遞歸演算法代碼顯得很簡潔,但遞歸演算法解題的運行效率較低。所以不提倡用遞歸設計程序。

【4】在遞歸調用的過程中系統為每一層的返回點、局部量等開辟了棧來存儲。遞歸次數過多容易造成棧溢出等,所以一般不提倡用遞歸演算法設計程序。

【5】在做遞歸演算法的時候,一定把握出口,也就是做遞歸演算法必須要有一個明確的遞歸結束條件。這一點是非常重要的。其實這個出口就是一個條件,當滿足了這個條件的時候我們就不再遞歸了。

三、代碼示例:

publicclassFactorial{

//thisisarecursivefunction

intfact(intn){

if(n==1)return1;

returnfact(n-1)*n;

}}
publicclassTestFactorial{publicstaticvoidmain(String[]args){

//TODOAuto-generatedmethodstub

Factorialfactorial=newFactorial();

System.out.println("factorial(5)="+factorial.fact(5));

}
}

代碼執行流程圖如下:

此程序中n=5就是程序的出口。

『柒』 遞歸演算法是什麼

遞歸演算法(英語:recursion algorithm)在計算機科學中是指一種通過重復將問題分解為同類的子問題而解決問題的方法。

遞歸式方法可以被用於解決很多的計算機科學問題,因此它是計算機科學中十分重要的一個概念。絕大多數編程語言支持函數的自調用,在這些語言中函數可以通過調用自身來進行遞歸。

計算理論可以證明遞歸的作用可以完全取代循環,因此在很多函數編程語言(如Scheme)中習慣用遞歸來實現循環。

『捌』 遞歸和迭代有什麼區別

一、含義不同:

遞歸是重復調用函數自身實現循環。迭代是函數內某段代碼實現循環,循環代碼中參與運算的變數同時是保存結果的變數,當前保存的結果作為下一次循環計算的初始值。

遞歸循環中,遇到滿足終止條件的情況時逐層返回來結束。迭代則使用計數器結束循環。當然很多情況都是多種循環混合採用,這要根據具體需求。

二、結構不同:

遞歸與迭代都是基於控制結構:迭代用重復結構,而遞歸用選擇結構。 遞歸與迭代都涉及重復:迭代顯式使用重復結構,而遞歸通過重復函數調用實現重復。

遞歸與迭代都涉及終止測試:迭代在循環條件失敗時終止,遞歸在遇到基本情況時終止,使用計數器控制重復的迭代和遞歸都逐漸到達終止點:迭代一直修改計數器,直到計數器值使循環條件失敗;遞歸不斷產生最初問題的簡化副本,直到達到基本情況。

遞歸演算法一般用於解決三類問題:

(1)數據的定義是按遞歸定義的。(Fibonacci函數)

(2)問題解法按遞歸演算法實現。

這類問題雖則本身沒有明顯的遞歸結構,但用遞歸求解比迭代求解更簡單,如Hanoi問題。

(3)數據的結構形式是按遞歸定義的。

如二叉樹、廣義表等,由於結構本身固有的遞歸特性,則它們的操作可遞歸地描述。

以上內容參考:網路-遞歸

『玖』 遞歸的原理解釋

遞歸的原理解釋:
遞歸,是函數實現的一個很重要的環節,很多程序中都或多或少的使用了遞歸函數。遞歸的意思就是函數自己調用自己本身,或者在自己函數調用的下級函數中調用自己。
遞歸之所以能實現,是因為函數的每個執行過程都在棧中有自己的形參和局部變數的拷貝,這些拷貝和函數的其他執行過程毫不相干。這種機制是當代大多數程序設計語言實現子程序結構的基礎,是使得遞歸成為可能。假定某個調用函數調用了一個被調用函數,再假定被調用函數又反過來調用了調用函數。這第二個調用就被稱為調用函數的遞歸,因為它發生在調用函數的當前執行過程運行完畢之前。而且,因為這個原先的調用函數、現在的被調用函數在棧中較低的位置有它獨立的一組參數和自變數,原先的參數和變數將不受影響,所以遞歸能正常工作。程序遍歷執行這些函數的過程就被稱為遞歸下降。
程序員需保證遞歸函數不會隨意改變靜態變數和全局變數的值,以避免在遞歸下降過程中的上層函數出錯。程序員還必須確保有一個終止條件來結束遞歸下降過程,並且返回到頂層。

熱點內容
pythonip合法性 發布:2025-01-16 04:48:52 瀏覽:75
鋰電池用3a的充電器是什麼配置 發布:2025-01-16 04:26:43 瀏覽:35
好配置為什麼感覺打聯盟不流暢 發布:2025-01-16 04:23:02 瀏覽:900
我的世界java編輯伺服器信息 發布:2025-01-16 04:21:42 瀏覽:507
android撥號上網 發布:2025-01-16 04:13:25 瀏覽:97
安卓網路編程怎麼用 發布:2025-01-16 03:04:45 瀏覽:899
湖南it伺服器怎麼樣 發布:2025-01-16 03:01:01 瀏覽:248
圖中兩種配置哪個好 發布:2025-01-16 02:59:28 瀏覽:582
如何解開密保密碼 發布:2025-01-16 02:57:44 瀏覽:23
中國銀行查詢密碼是什麼 發布:2025-01-16 02:33:20 瀏覽:796