『壹』 c語言怎麼計算遞歸次數
遞歸就是有限次的嵌套調用函數本身,要知道遞歸的次數,就找出調用中變化量到結束調用的判斷點,這之間的變數變化次數等於順推次數,返回個數等於順推次數,這樣就可以計算出總的次數
『貳』 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*3*4*5 ;
#include< iostream >
using namespace std;
int Fun( int val )
{
if( n > 1 )
return val * Fun( val - 1 ); // 最難理解的相信就是這一步吧
return val;
}
int main()
{
cout << Fun( 5 ) << endl ;
return 0;
}
首先,第一次調用Fun函數時,val == 5;
所以好好分析一下這段代碼
if( val > 1 )
return val * Fun( val - 1 ) ;
第一次調用時 val == 5, 條件成立, 函數返回 val( 等於5那個 )乘以用實參 4 ( 也就是val - 1 的值 ) 調用的那個函數的返回值( 也就是自身 )...
看到這里先不要頭暈, 這只是第一步,還有很多步調用,其實跟循環是差不多的.
函數調用有一個返回值, 如果返回值是一個表達式,就先求解表達式的值再返回,被函數返回時從調用函數處的下一個語句繼續執行,如果沒有理解C語言的這兩句話,這就很難理解遞歸了.
下面是整個程序的流程
1, 用 val == 5 調用 Fun, 執行到 if 語句, 條件成立 執行 return val * Fun( val - 1 ), 由於函數調用操作符 () 優先順序高於算術操作符, 因此表達式的求解順序是先調用函數, 再 用 val * 返回值;
2, 用 val == 4 的值調用 Fun,後面的步驟和用 val == 5調用 Fun 的步驟是一樣的;
3, 用 val == 3 的值調用 Fun;
4, 用 val == 2 的值調用 Fun;
5, 用 val == 1 的值調用 Fun, 這時的 if 語句條件不成立, 於是執行後面的
return val 的值( == 1 );
6, 那這個 val == 1 的值返回到哪裡去了呢? 剛接觸遞歸的人可能會很容易聯想到是 main 函數調用 Fun 的, 那這個值也返回到 main 函數中去了. 其實不是,返回值為1的Fun函數是誰調用的?是 val == 2 時的Fun函數調用的,也就是第4步的if 語句後面的表達式是 return 2 * Fun( 2 - 1 ),理解這點就好辦了,第六步就開始求解前面還沒執行的算術操作( 由於函數調用操作符 () 優先順序高於算術操作符, 因此表達式的求解順序是先調用函數 ).也就是把第5步的返回值用於求解第4步時里的表達式;
7, 在上一步驟中,求解出 2 * Fun( val - 1 )的值, 又把它返回給它的調用者
,就是把值 3 返回至第3步;
8, 把第3步的得出的值返回第2步;
9, 把第2 步得出的值返回第1步;
10, 在第1步,記得這次調用是main函數調用的,因此返回到main函數中的cout << Fun( 5 ) << endl, 輸出結果;
整個遞歸過程就完成了,可以看到遞歸也是一個循環,但它比一般的循環計算的步驟多了很多,所以它的效率普遍是比較低的,而且操作系統把每一次的調用裝進一個棧中記錄起來,它耗費的內存也是比較大的,在深層的遞歸調用或在遞歸函數中定義較大的數據容易造成棧溢出,但有時( 對初學者來說不見得 )用它來解決問題卻能讓代碼清晰,容易編寫.
『肆』 c語言求遞歸次數
遞歸次數,設一個全局變數計數就可以了
int count = 0;
在move中添加 count++;
『伍』 C語言怎麼計算遞歸次數
perm1()函數中定義一個靜態變數用於計數,調用該函數的時候計數器自增。顯示函數多傳入一個排列序號。如下所示:
void perm1(int *p,int n,int m)
{
void swap(int *data1,int *data2);
void output(int index,int *p,int n); //多傳入一個排列序號
static s_cnt = 0;//計數器
int i;
s_cnt++;//計數器自增
if(m==(n-1)){
output(s_cnt,p,n);
}
else{
for(i=m;i<n;i++){
swap(&p[i],&p[m]);
perm1(p,n,m+1);
swap(&p[i],&p[m]);
}
}
}
void output(int index,int *p,int n)
{
printf("------------------\n");
printf("Index: %d", index);//顯示序號
//printf("time=%d\n",m);
int i;
for(i=0;i<n;i++){
printf("p[%d]=%d\n",i,p[i]);
}
}
『陸』 用C語言的函數遞歸方法來求
#include <stdio.h>
#include <math.h>
void fun2(int m)
{
int k=0,a[10];
for(int i=2;i<m;i++)
if(m%i==0)
a[k++]=i;
for(int i=0;i<k;i++)
{
printf("%d",a[i]);
if(i!=k-1)
printf(",");
}
}
void fun1(int m)
{
if(m<2)
printf("%d is a prime number",m);
for(int i=2;i*i<=m;i++)
if(m%i==0)
fun2(m);
else
printf("%d is a prime number",m);
}
int main( )
{ int n;
scanf("%d",&n);
fun1(n);
return 0;
}
『柒』 C語言函數遞歸計算
#include<stdio.h>
#include<stdlib.h>
intcount=0;
intfun(intx,intn)
{
count++;
if(n==2)
{
returnx*x;
}
elseif(n%2==0)
{
returnfun(x,n/2)*fun(x,n/2);
}
elseif(n%2==1)
{
returnfun(x,n-1)*x;
}
}
intmain(intargc,char*argv[]){
intsum=0,x,n;
printf("請輸入xn的值(兩數之間用空格間隔):");
scanf("%d%d",&x,&n);
sum=fun(x,n);
printf("%d遞歸調用了%d次",sum,count);
return0;
}
『捌』 c語言函數遞歸的演算法
這是一個遞歸調用fun(x)的演算法。
首先會計算x=1時,因為x是int型,所以x/2==0,返回1,所以列印1.
然後再計算x=2時,這時返回x%2=0,所以列印0;
再計算x=4時,同樣返回x%2=0,所以列印0;
最後計算x=8時,返回x%2=0,所以列印0。
所以屏幕輸出的就顯示1000 。
『玖』 C語言中遞歸次數怎麼輸出
使用一個全局變數,在main中初始化,在遞歸的函數中將這個變數加一,在使用遞歸函數前把變數清零,使用遞歸函數後,這個變數值就是遞歸的次數。
『拾』 c語言遞歸演算法
用遞歸法計算n!
用遞歸法計算n!可用下述公式表示:
n!=1 (n=0,1)
n×(n-1)! (n>1)
按公式可編程如下:
long ff(int n)
{
long f;
if(n<0) printf("n<0,input error");
else if(n==0||n==1) f=1;
else f=ff(n-1)*n;
return(f);
}
main()
{
int n;
long y;
printf("\ninput a inteager number:\n");
scanf("%d",&n);
y=ff(n);
printf("%d!=%ld",n,y);
}
程序中給出的函數ff是一個遞歸函數。主函數調用ff 後即進入函數ff執行,如果n<0,n==0或n=1時都將結束函數的執行,否則就遞歸調用ff函數自身。由於每次遞歸調用的實參為n-1,即把n-1的值賦予形參n,最後當n-1的值為1時再作遞歸調用,形參n的值也為1,將使遞歸終止。然後可逐層退回。
下面我們再舉例說明該過程。設執行本程序時輸入為5,即求5!。在主函數中的調用語句即為y=ff(5),進入ff函數後,由於n=5,不等於0或1,故應執行f=ff(n-1)*n,即f=ff(5-1)*5。該語句對ff作遞歸調用即ff(4)。
進行四次遞歸調用後,ff函數形參取得的值變為1,故不再繼續遞歸調用而開始逐層返回主調函數。ff(1)的函數返回值為1,ff(2)的返回值為1*2=2,ff(3)的返回值為2*3=6,ff(4)的返回值為6*4=24,最後返回值ff(5)為24*5=120。