最近學習到了遞迴,剛開始看,真是頭大,函式裡面巢狀其本身,到底是怎麼個流程啊?
現在,咱們先了解下遞迴函式的數學原理:
高中的時候就出現很多遞迴函式,應該是在「級數」那裡的習題中出現的,而且還不少。還是從例子開始吧:
f(x)=f(x-1)+x*x ,
其中x>0
且f(0)=0
求f(4)
解:
由於f(0)=0:
當x=1
時f(1)=f(0)+1*1=1;
當x=2
時f(2)=f(1)+2*2=5;
當x=3
時f(3)=f(2)+3*3=14;
當x=4
時f(4)=f(3)+4*4=30;
所以, f(4)=30.
上學的時候,可能會這樣做出來。
f(x)=f(x-1)+x*x ,其中x>0且f(0)=0
就是乙個遞迴函式,它用到了
f(x)
是用f(x-1)
定義的。
細心的人還可以發現
x>0且f(0)=0
也是函式的一部分:
x>0提供乙個遞迴區間,而
f(0)=0
提供了乙個初始條件(思維方向不同,在電腦思維中這個條件為終止條件,詳見下文)
。或許大家覺得和我們課堂上的遞迴還是有點不同,不同在哪呢?
這就是人腦和電腦的區別:
電腦不會直接去找初始條件去向問題遞推。
而是從問題出發,遞推下去,直到找到終止條件
(解題時的初始條件)。
電腦思維
: f(4)=f(3)+4*4;
f(3)=f(2)+3*3
f(2)=f(1)+2*2
f(1)=f(0)+1*1
f(0)=0; //
終止條件
f(1)=f(0)+1*1=1;
f(2)=f(1)+2*2=5;
f(3)=f(2)+3*3=14;
f(4)=f(3)+4*4=30;
這個是電腦的思維過程,也就是計算過程,不會在前台顯示出來。
「遇到問題,解決問題,輸出結果」——這是電腦處理問題的流程。
關鍵在於,怎麼寫個遞迴函式讓電腦認識。
明白遞迴函式的定義,其實很簡單。
遞迴函式有三個充分條件:第一是函式體,第二是遞迴區間,第三個是終止條件,
只要在**中全部申明出來,乙個遞迴函式的就寫出來了。
上面的遞迴函式的就可以寫出下面的**:
[cpp]view plain
copy
function squaresum($x)
echo squaresum(4); //輸出30
其中用到了if...elseif…語句,這就是來宣告遞迴函式的遞迴區間和終止條件
(x>0且f(0)=0)的。
現在在來寫乙個正整數n的n!的遞迴函式就思路很明確了。
分析:正整數n , f(n)=n! =>
函式體:f(n)=n*f(n-1);遞迴區間:n.> 1;終止條件:n=1;
[cpp]view plain
copy
function rank($n)
由此我們可以發現當要寫乙個遞迴函式,找到終止條件,乙個遞迴函式就很明朗了,剩下就是語法問題了
到linux c這塊,我們做乙個例題:
例:求斐波那契數列第n項。斐波那契數列的第一項和第二項是1,後面每一項是前兩項之和,即1,1,2,3,5,8,13,。。。
下面程式採用直接遞迴呼叫:
[cpp]view plain
copy
#include
long
fib(
intn)
intmain()
程式執行結果如下:
[cpp]view plain
copy
fs@ubuntu:~/qiang/digui$ ./digui1
1 1 2 3 5 8 13 21
遞迴的條件:
上面已經簡單提到,現在再說明一下
乙個問題能否用遞迴來實現,看其是否有如下特點:
1、須有完成函式任務的語句。
例如:下面的**定義了乙個遞迴函式
[cpp]view plain
copy
#include
void
count(
intval)
該函式的任務是在輸出裝置上顯示」ok: 整數值「。
2、乙個任務是否能夠避免遞迴呼叫的測試。
例如,上面的**中,語句"if (val > 1)"便是乙個測試,如果不滿足條件,就不進行遞迴呼叫。
3、乙個遞迴呼叫語句
該遞迴呼叫語句的引數應該逐漸逼近不滿足條件,以至最後斷絕遞迴。
例如,上面的**彙總,語句 "if( val > 1)"便是乙個遞迴呼叫,引數在漸漸變小,這話總發展趨勢能使測試 "if (val > 1)"最終不滿足。
4,、先測試,後遞迴呼叫
在遞迴函式定義中,必須先測試,後遞迴呼叫。也就是說,遞迴呼叫是有條件的,滿足了條件,才可以遞迴。
例如,下面的**無限制的呼叫函式自己,造成無限制遞迴,終將使棧空間溢位;
[cpp]view plain
copy
#include
void
count(
intval)
下面是完整程式:
[cpp]view plain
copy
#include
void
count(
intval)
intmain()
程式執行結果如下:
[cpp]view plain
copy
fs@ubuntu:~/qiang/digui$ vi digui2.c
fs@ubuntu:~/qiang/digui$ gcc -o digui2 digui2.c
fs@ubuntu:~/qiang/digui$ ./digui2
ok:1
ok:2
ok:3
ok:4
ok:5
ok:6
ok:7
ok:8
ok:9
ok:10
fs@ubuntu:~/qiang/digui$
遞迴的應用會繼續更新,比如在二叉樹的遍歷
Linux C學習 getline 函式
getline不是c庫函式,而是c 庫函式。它會生成乙個包含一串從輸入流讀入的字元的字串,直到以下情況發生會導致生成的此字串結束。1 到檔案結束,2 遇到函式的定界符,3 輸入達到最大限度。linux標準c中使用條件 define gnu source include 函式宣告 ssize t ge...
linux c學習筆記 select函式詳解
select系統呼叫是用來讓我們的程式監視多個檔案控制代碼 file descriptor 的狀態變化的。程式會停在select這裡等待,直到被監視的檔案控制代碼有某乙個或多個發生了狀態改變。何為檔案控制代碼?檔案控制代碼在linux裡很多,如果你man某個函式,在函式返回值部分說到成功後有乙個檔案...
Linux C 函式總結
linux c 的記憶體分配 3個儲存空間動態分配和乙個記憶體釋放的函式 malloc 記憶體分配指定位元組儲存區,初始值不為0 calloc 為指定個數的具有指定長度的物件分配儲存空間,每一位初始化為0 reallco 更改以前的分配區長度 可增,可減 當增加時,將以前的分配區內容遷移到乙個足夠大...