當前位置:首頁 » 編程語言 » c語言中雙遞歸
擴展閱讀
怎麼清除預覽圖片的緩存 2022-11-30 14:15:11
c語言創建有序鏈表 2022-11-30 14:08:06

c語言中雙遞歸

發布時間: 2022-11-25 03:33:18

c語言中的遞歸函數

當需要返回值時就return.程序因此不死循環。正不正確,運行一下通過就應該ok.

Ⅱ 在C語言中什麼叫遞歸

遞歸:就是自己調自己,但是沒終止條件會死循環,所以你的遞歸代碼里有結束自調自的條件,這樣就創造了有限次的循環(代碼中你看不到for或foreach但是有循環發生)

Ⅲ c語言遞歸的方法是什麼

思路:使用遞歸主要有兩點需要注意,一個是遞歸計算公式,二是遞歸跳出條件。 參考代碼: #includeint fun(int n){if(n==0) return 0;//遞歸跳出條件 return n+fun(n-1);//遞歸計算公式 }int main(){int n;scanf("%d",&n); printf("%d\n",fun(n)

Ⅳ C語言什麼是遞歸方法

編程裡面估計最讓人摸不著頭腦的基本演算法就是遞歸了。很多時候我們看明白一個復雜的遞歸都有點費時間,尤其對模型所描述的問題概念不清的時候,想要自己設計一個遞歸那麼就更是有難度了。今天我也花費了半個小時來搞明白二叉樹的平衡性的遞歸模型,首先我不明白什麼叫做平衡性,所以花費的時候大部分實在試探理解平衡性的含義。在搞明白的時候,我突然想到假如讓我來設計,在我知道平衡性的前提下,我是否可以建立如此簡潔的遞歸模型。為此,我遇到的問題是我們到底在什麼情況下適用遞歸模型,並且遞歸模型如何建立。


數學都不差的我們,第一反應就是遞歸在數學上的模型是什麼。畢竟我們對於問題進行數學建模比起代碼建模拿手多了。 (當然如果對於問題很清楚的人也可以直接簡歷遞歸模型了,運用數模做中介的是針對對於那些問題還不是很清楚的人)


自己觀察遞歸,我們會發現,遞歸的數學模型其實就是歸納法,這個在高中的數列裡面是最常用的了。回憶一下歸納法。


歸納法適用於想解決一個問題轉化為解決他的子問題,而他的子問題又變成子問題的子問題,而且我們發現這些問題其實都是一個模型,也就是說存在相同的邏輯歸納處理項。當然有一個是例外的,也就是遞歸結束的哪一個處理方法不適用於我們的歸納處理項,當然也不能適用,否則我們就無窮遞歸了。這里又引出了一個歸納終結點以及直接求解的表達式。如果運用列表來形容歸納法就是:


步進表達式:問題蛻變成子問題的表達式

結束條件:什麼時候可以不再是用步進表達式

直接求解表達式:在結束條件下能夠直接計算返回值的表達式

邏輯歸納項:適用於一切非適用於結束條件的子問題的處理,當然上面的步進表達式其實就是包含在這裡面了。


這樣其實就結束了,遞歸也就出來了。

遞歸演算法的一般形式:

voidfunc(mode)
{
if(endCondition)
{
constExpression//基本項
}
else
{
accumrateExpreesion/歸納項
mode=expression//步進表達式
func(mode)//調用本身,遞歸
}
}

最典型的就是N!演算法,這個最具有說服力。理解了遞歸的思想以及使用場景,基本就能自己設計了,當然要想和其他演算法結合起來使用,還需要不斷實踐與總結了。

例如:返回一個二叉樹的深度:

intdepth(Treet){
if(!t)return0;
else{
inta=depth(t.right);
intb=depth(t.left);
return(a>b)?(a+1):(b+1);
}
}


判斷一個二叉樹是否平衡:

intisB(Treet){
if(!t)return0;
intleft=isB(t.left);
intright=isB(t.right);
if(left>=0&&right>=0&&left-right<=1||left-right>=-1)
return(left<right)?(right+1):(left+1);
elsereturn-1;
}


上面這兩個遞歸的難易程度就不一樣了,第一個關於深度的遞歸估計只要了解遞歸思想的都可以短時間設計出來,但第二個估計就要長點時間了。純遞歸問題的難易主要糾結於一些條件表達式的構造以及初值的設置(上面的為直接表達式值的設定)。

最後需要補充的是,很多不理解遞歸的人,總認為遞歸完全沒必要,用循環就可以實現,其實這是一種很膚淺的理解。因為遞歸之所以在程序中能風靡並不是因為他的循環,大家都知道遞歸分兩步,遞和歸,那麼可以知道遞歸對於空間性能來說,簡直就是造孽,這對於追求時空完美的人來說,簡直無法接接受,如果遞歸僅僅是循環,估計現在我們就看不到遞歸了。遞歸之所以現在還存在是因為遞歸可以產生無限循環體,也就是說有可能產生100層也可能10000層for循環。例如對於一個字元串進行全排列,字元串長度不定,那麼如果你用循環來實現,你會發現你根本寫不出來,這個時候就要調用遞歸,而且在遞歸模型裡面還可以使用分支遞歸,例如for循環與遞歸嵌套,或者這節枚舉幾個遞歸步進表達式,每一個形成一個遞歸。

Ⅳ 講一下c語言中遞歸函數的使用方法

相當於循環,要有判斷條件,傳遞進去的參數要變化,滿足條件調用自身,不滿足條件就開始一層一層返回。簡單例子:
int
f(int
i){
int
sum=0;
if(i>0)
sum+=f(i-1);
return
sum;
}
main(){
int
a=10;
printf("%d",f(a));
}

Ⅵ C語言關於函數的遞歸

你的遞歸程序是錯的,我轉來個對的,帶講解的,你看看。

語言函數的遞歸和調用

一、基本內容:

C語言中的函數可以遞歸調用,即:可以直接(簡單遞歸)或間接(間接遞歸)地自己調自己。

要點:

1、C語言函數可以遞歸調用。

2、可以通過直接或間接兩種方式調用。目前只討論直接遞歸調用。

二、遞歸條件

採用遞歸方法來解決問題,必須符合以下三個條件:

1、可以把要解決的問題轉化為一個新問題,而這個新的問題的解決方法仍與原來的解決方法相同,只是所處理的對象有規律地遞增或遞減。

說明:解決問題的方法相同,調用函數的參數每次不同(有規律的遞增或遞減),如果沒有規律也就不能適用遞歸調用。

2、可以應用這個轉化過程使問題得到解決。

說明:使用其他的辦法比較麻煩或很難解決,而使用遞歸的方法可以很好地解決問題。

3、必定要有一個明確的結束遞歸的條件。

說明:一定要能夠在適當的地方結束遞歸調用。不然可能導致系統崩潰。

三、遞歸實例

例:使用遞歸的方法求n!

當n>1時,求n!的問題可以轉化為n*(n-1)!的新問題。

比如n=5:

第一部分:5*4*3*2*1 n*(n-1)!

第二部分:4*3*2*1 (n-1)*(n-2)!

第三部分:3*2*1 (n-2)(n-3)!

第四部分:2*1 (n-3)(n-4)!

第五部分:1 (n-5)! 5-5=0,得到值1,結束遞歸。

源程序:
fac(int n)
{int t;
if(n==1)||(n==0) return 1;
else
{ t=n*fac(n-1);
return t;
}
}
main( )
{int m,y;
printf(「Enter m:」);
scanf(「%d」,&m);
if(m<0) printf(「Input data Error!\n」);
else
{y=fac(m);
printf(「\n%d! =%d \n」,m,y);
}
}

四、遞歸說明

1、當函數自己調用自己時,系統將自動把函數中當前的變數和形參暫時保留起來,在新一輪的調用過程中,系統為新調用的函數所用到的變數和形參開辟另外的存儲單元(內存空間)。每次調用函數所使用的變數在不同的內存空間。

2、遞歸調用的層次越多,同名變數的佔用的存儲單元也就越多。一定要記住,每次函數的調用,系統都會為該函數的變數開辟新的內存空間。

3、當本次調用的函數運行結束時,系統將釋放本次調用時所佔用的內存空間。程序的流程返回到上一層的調用點,同時取得當初進入該層時,函數中的變數和形參所佔用的內存空間的數據。

4、所有遞歸問題都可以用非遞歸的方法來解決,但對於一些比較復雜的遞歸問題用非遞歸的方法往往使程序變得十分復雜難以讀懂,而函數的遞歸調用在解決這類問題時能使程序簡潔明了有較好的可讀性;但由於遞歸調用過程中,系統要為每一層調用中的變數開辟內存空間、要記住每一層調用後的返回點、要增加許多額外的開銷,因此函數的遞歸調用通常會降低程序的運行效率。

五、程序流程

fac(int n) /*每次調用使用不同的參數*/
{ int t; /*每次調用都會為變數t開辟不同的內存空間*/
if(n==1)||(n==0) /*當滿足這些條件返回1 */
return 1;
else
{ t=n*fac(n-1); /*每次程序運行到此處就會用n-1作為參數再調用一次本函數,此處是調用點*/
return t; /*只有在上一句調用的所有過程全部結束時才運行到此處。*/
}
}

Ⅶ C語言中的遞歸是什麼意思

程序調用自身的編程技巧稱為遞歸( recursion)。遞歸做為一種演算法在程序設計語言中廣泛應用。 一個過程或函數在其定義或說明中有直接或間接調用自身的一種方法,它通常把一個大型復雜的問題層層轉化為一個與原問題相似的規模較小的問題來求解。

遞歸策略只需少量的程序就可描述出解題過程所需要的多次重復計算,大大地減少了程序的代碼量。遞歸的能力在於用有限的語句來定義對象的無限集合。

一般來說,遞歸需要有邊界條件、遞歸前進段和遞歸返回段。當邊界條件不滿足時,遞歸前進;當邊界條件滿足時,遞歸返回。



(7)c語言中雙遞歸擴展閱讀:

遞歸的應用

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

2、問題解法按遞歸演算法實現。這類問題雖則本身沒有明顯的遞歸結構,但用遞歸求解比迭代求解更簡單,如Hanoi問題。

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

遞歸的缺點

遞歸演算法解題相對常用的演算法如普通循環等,運行效率較低。因此,應該盡量避免使用遞歸,除非沒有更好的演算法或者某種特定情況,遞歸更為適合的時候。在遞歸調用的過程當中系統為每一層的返回點、局部量等開辟了棧來存儲。遞歸次數過多容易造成棧溢出等。


Ⅷ 講一下c語言中遞歸函數的使用方法

遞歸函數有三點要求:

1,遞歸的終止點,即遞歸函數的出口

2,不斷的遞歸調用自身

3,遞歸函數主體內容,即遞歸函數需要做的事情

ps:3一般可以放在2的前面或者後面,一般1放最前面。另外,2和3可以根據不同的需要合並,比如,有時候遞歸函數的主體就是返回調用下層函數所得到的結果。

具體例子如下:

voidfun(intn)
{
if(n<=0)return;//1這是遞歸的終點,即出口
fun(n-1);//2、遞歸函數自身的調用
cout<<n<<endl;//3遞歸函數的主體內容
}


2,3合並的情況

intfun(intn)
{
if(n<=0)return0;
returnfun(n-1)+fun(n-2);//23合並
}

Ⅸ 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。

Ⅹ 請問這裡面的雙重遞歸怎麼去理解,或者這是屬於什麼方面的知識,我剛大一,C語言學了一學期,求大神。

哪裡面的?雙重遞歸就是在一個遞歸函數里兩次調用自身。

比如求解斐波那契數列的時候f(n)=f(n-1)+f(n-2).