Linux C學習 遞迴函式

2021-08-17 00:09:11 字數 3384 閱讀 6327

最近學習到了遞迴,剛開始看,真是頭大,函式裡面巢狀其本身,到底是怎麼個流程啊?

現在,咱們先了解下遞迴函式的數學原理:

高中的時候就出現很多遞迴函式,應該是在「級數」那裡的習題中出現的,而且還不少。還是從例子開始吧: 

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 更改以前的分配區長度 可增,可減 當增加時,將以前的分配區內容遷移到乙個足夠大...