遞歸(英語:recursion)在計算機科學中是指一種經過重複將問題分解爲同類的子問題而解決問題的方法。[1] 遞歸式方法能夠被用於解決不少的計算機科學問題,所以它是計算機科學中十分重要的一個概念。[2] 絕大多數編程語言支持函數的自調用,在這些語言中函數能夠經過調用自身來進行遞歸。計算理論能夠證實遞歸的做用能夠徹底取代循環,所以有不少在函數編程語言(如Scheme)中用遞歸來取代循環的例子。(摘自維基百科)編程
在計算機學裏,尾調用是指一個函數裏的最後一個動做是返回一個函數的調用結果的情形,即最後一步新調用的返回值直接被當前函數的返回結果。[1]此時,該尾部調用位置被稱爲尾位置。尾調用中有一種重要而特殊的情形叫作尾遞歸。通過適當處理,尾遞歸形式的函數的運行效率能夠被極大地優化。[1]尾調用原則上均可以經過簡化函數調用棧的結構而得到性能優化(稱爲「尾調用消除」),可是優化尾調用是否方即可行取決於運行環境對此類優化的支持程度如何。(摘自維基百科)性能優化
【編程題】冪運算三(遞歸函數)
題目ID:1137
【問題描述】 求x^n。
【輸入形式】一行2個數,第一個整數表示x,第二個大於等於零的整數表示n,二數之間用空格分隔。
【輸出形式】一行一個整數,表示x的n次方
【樣例輸入】2 3
【樣例輸出】8編程語言
【樣例說明】2的3次方結果爲8
【評分標準】5組測試用例,每組2分,共計10分 函數
【測試用例】
1)
輸入:
2 3
輸出:
8
2)
輸入:
3 5
輸出:
243性能
3)
輸入:
-17 4
輸出:
83521測試
4)
輸入:
22 0
輸出:
1優化
5)
輸入:
-1287 0
輸出:
1spa
//普通遞歸 #include<stdio.h> long my_pow1(long x,int n){ if(n==0) return 1; //遞歸出口 return x*(my_pow1(x,--n)); //除了調用自身外還乘多了個x,即通常的遞歸 } int main(){ long x; int n; scanf("%ld%d",&x,&n); printf("%ld\n",my_pow1(x,n)); return 0; }
解釋:
普通的遞歸過程是在一個函數中,結果依靠自身的調用來得出,例如求冪運算,pow(2,3)
表明求2的3次方,因爲pow(2,3)
未知,咱們能夠把它分解成2*pow(2,2),pow(2,2)也未知,又可分解成2*pow(2,1),以此類推,直到pow(2,0)可知(if中定義0時返回1),即pow(2,0)返回值是1.
在這個遞歸過程當中,pow函數的創建就是一個個壓棧的過程
我把它稱爲函數棧3d
壓棧壓入因此函數後,直到最後一個,能夠得到最後一個函數的返回值,由這個返回值能夠依次推出棧內全部函數的返回值(回溯),即退棧,pow(2,0)返回1,推的pow(2,1)返回2*pow(2,0),即2*1=2,pow(2,2)返回2*pow(2,1),即2*2=4,直到退到棧內最後一個函數pow(2,3),可得到pow(2,3)的返回值爲2*pow(2,2)即8;
code
【編程題】吃糖(尾遞歸函數)
題目ID:1135
【問題描述】小櫻是個愛吃糖的女孩, 哥哥送了她n(1<=n<=30)顆糖,怎麼吃?一天吃1顆;一天吃2顆。嗯,那就天天吃一顆或兩顆吧。
1顆糖,確定只有(1)一種吃法;2顆糖,有(1,1)和(2)兩種吃法;3顆糖,有(1,1,1)、(1,2)和(2,1)三種吃法。注 (2,1)表示第一天吃2顆,次日吃1顆。*
你能幫小櫻算出,吃完這n顆糖,有多少種吃法嗎?請編寫一個尾遞歸函數來解決此問題
【輸入形式】
【測試用例】
1)
輸入:
1
輸出:
result=1
2)
輸入:
4
輸出:
result=5
3)
輸入:
15
輸出:
result=987
4)
輸入:
20
輸出:
result=10946
5)
輸入:
30
輸出:
result=1346269
實際上這道題是一個斐波那契數列的變體,可用尾遞歸函數解決
//尾遞歸 #include <stdio.h> int ci(int n,int pre,int next) { int sum; if (n==1){ //遞歸出口(遞歸和回溯的分界點) return pre; } return ci(n-1,next,pre+next); //除了調用自身外沒有其餘操做即爲尾遞歸 } int main() { int n; int sum; scanf ("%d",&n); printf ("result=%d",ci(n,1,2)); return 0; }
運行圖解
解釋:
ci(1,5,8)得到了返回值5,ci(2,3,5)的返回值是ci(1,5,8),也就是5,ci(3,2,3)的返回值是ci(2,3,5),也就是5,ci(4,1,2)的返回值也是5;
而已,ci(4,1,2),4是要求斐波那契變體的第4項,1是第一項,2是第二項,從4減到1起到一個計數做用,1和2也是做爲遞推的起點
*下圖是普通遞歸和尾遞歸的執行圖示: