遞迴函式與棧

2021-08-28 13:48:36 字數 1761 閱讀 5002

關於函式呼叫與棧的關係:鏈結

下面是在函式呼叫與棧的關係的基礎上,為了解遞迴呼叫的筆記。

為了方便描述,將乙個函式f(x)的棧幀以下圖的方式進行簡化:

並用乙個求階乘的函式來解釋遞迴函式與棧的聯絡:

int

fun(

int n)

intmain

(int argc,

char

**argv)

首先程式從主函式開始,第乙個壓入的是主程式的棧幀。每個程式(函式)都會有自己的棧幀,主程式當然是不會例外的,況且主程式也是由另乙個程式所呼叫的(比如shell)。此時棧中的情況:

在執行主程式時,需要呼叫fun函式,引數為3,此時就需要壓入引數為3的fun函式的棧幀。棧中情況如下:

當執行fun(3)時,由於n不等於1,因此需要在fun(3)中呼叫fun(3-1)即fun(2),此時需要再壓入引數為2的fun函式。棧中情況如下:

此時執行fun(2),但是fun(2)的引數n=2仍然不等於1,因此需要在fun(2)中呼叫fun(2-1)即fun(1),此時需要再壓入引數為1的fun函式。棧中情況如下:

這時執行的fun(1)的引數n=1滿足了等於1的條件,因此不用再呼叫自己了。fun(1)返回1(該返回值在%eax暫存器中)並將其棧幀彈出恢復到fun(2)呼叫fun(1)時的狀態:

fun(2)通過暫存器%eax中的值(即fun(1)的返回值),計算出nfun(n-1)為2,並將該值儲存在%eax作為返回值。最後同樣彈出自己的棧幀恢復到fun(3)呼叫fun(2)時的狀態:

同理,fun(3)通過fun(2)的返回值計算出nfun(n-1)為6,並將該值儲存在%eax作為返回值。最後彈出自己的棧幀恢復到main函式呼叫fun(3)時的狀態:

最後main函式也執行完了,將返回值0返回給某乙個程式(如常見的shell)並彈出自己的棧幀:

從上面也就可以理解,無窮的遞迴也只能存在於邏輯之中。如果沒有基線條件(即n == 1),棧就會不斷地被棧幀填壓,最後必然會導致記憶體不足。避免過深的遞迴也是同樣的道理。

基線條件指的是停止遞迴的條件。

函式遞迴與棧的實用

問題 求斐波那契數列的遞迴方法與非遞迴方法 棧是一種應用範圍廣泛的資料結構,適用於各種具有 後進先出 特性的問題。遞迴函式是指在乙個函式 過程或資料結構的定義中又應用了它自身的函式。include include using std cout using std endl using std sta...

遞推與遞迴 棧

棧是計算機中經典的資料結構,簡單的說,棧就是限制在一端進行插入刪除操作的線性表。棧有兩種最重要的操作,即 pop 從棧頂彈出乙個元素 和 push 將乙個元素進棧 棧的重要性不言自明,任何一門資料結構的課程都會介紹棧。寧寧同學在複習棧的基本概念時,想到了乙個書上沒有講過的問題,而他自己無法給出答案,...

遞迴函式的棧表達

void recursive m r m if m in a p m recursive l m q m recursive r m s m else ret m 分兩類操作 1.cws 表示當前工作棧的引數m 如果cws滿足in a 將能新增的左子結點全部新增入棧中,之後將尾部的不符合in a的執...