函式的遞迴和堆疊

2022-09-13 10:18:13 字數 2491 閱讀 4841

之前學遞迴一直學的迷迷糊糊,感覺懂了又感覺沒懂,今天正好學習到了這一部分。

當函式解決乙個任務時,在解決的過程中它可能會呼叫很多其他函式。當函式呼叫自身時,就是所謂的遞迴

舉乙個例子:

乙個函式pow(x,n),計算x的n次方。

遞迴思路:

1

function

pow(x, n) else7}

89 alert( pow(2, 3) ); //

8

函式執行分為兩個分支:

1、如果n == 1,函式會立即產生明顯的結果,這叫做基礎的遞迴

2、else,這個分支叫做乙個遞迴步驟:將任務轉化為更簡單的行為(x的乘法)和更簡單的同類任務(帶有更小的n的pow運算)的呼叫。接下來的步驟將其進一步簡化,直到n到達1。

比如,為了計算pow(2, 4),遞迴變體經過了下面幾個步驟:

pow(2, 4) = 2 * pow(2, 3)

pow(2, 3) = 2 * pow(2, 2)

pow(2, 2) = 2 * pow(2, 1)

pow(2, 1) = 2

到這裡之前也是懂的,接下來研究一下遞迴呼叫的工作原理。

執行上下文是乙個內部資料結構,它包含有關函式執行時的詳細細節:當前控制流所在的位置,當前的變數,this的值(此處我們不使用它),以及其它的一些內部細節。

乙個函式呼叫僅具有乙個與其相關聯的執行上下文。

當乙個函式進行巢狀呼叫時,將發生以下的事兒:

讓我們看看pow(2, 3)呼叫期間都發生了什麼。

pow(2, 3)

在呼叫pow(2, 3)的開始,執行上下文(context)會儲存變數:x = 2, n = 3,執行流程在函式的第1行。

我們將其描繪如下:

這是函式開始執行的時候。條件n == 1結果為 false,所以執行流程進入if的第二分支。

變數相同,但是行改變了,因此現在的上下文是:

為了計算x * pow(x, n - 1),我們需要使用帶有新引數的新的pow子呼叫pow(2, 2)

pow(2,2)

為了執行巢狀呼叫,j**ascript 會在執行上下文堆疊中記住當前的執行上下文。

這裡我們呼叫相同的函式pow,所有函式的處理都是一樣的:

當前上下文被「記錄」在堆疊的頂部。

為子呼叫建立新的上下文。

當子呼叫結束後 —— 前乙個上下文被從堆疊中彈出,並繼續執行

下面是進入子呼叫pow(2, 2)時的上下文堆疊:

新的當前執行上下文位於頂部(粗體顯示),之前記住的上下文位於下方。

當我們完成子呼叫後 —— 很容易恢復上乙個上下文,因為它既保留了變數,也保留了當時所在**的確切位置。

pow(2,1)

這是當pow(2,1)時,函式的執行上下文堆疊,現在的引數是x=2,n=1,

新的執行上下文被建立,前乙個被壓入堆疊頂部:

此時,有2個舊的上下文和乙個當前正在執行的pow(2,1)的上下文。

出口

在執行pow(2, 1)時,與之前的不同,條件n == 1為 true,因此if的第乙個分支生效:

此時不再有更多的巢狀呼叫,所以函式結束,返回2

函式完成後,就不再需要其執行上下文了,因此它被從記憶體中移除。前乙個上下文恢復到堆疊的頂部:

恢復執行pow(2, 2)。它擁有子呼叫pow(2, 1)的結果,因此也可以完成x * pow(x, n - 1)的執行,並返回4

然後,前乙個上下文被恢復:

當它結束後,我們得到了結果pow(2, 3) = 8

本示例中的遞迴深度為:3

遞迴深度:最大的巢狀呼叫次數(包括首次)。

從上面我們可以看出,遞迴深度等於堆疊中上下文的最大數量。

使用遞迴時需要注意記憶體,上下文占用記憶體。

參考文獻:

學習記錄 遞迴和堆疊

今天在學習遞迴和堆疊的知識 1 中,使用堆疊進行求和運算過程中遇到了 deque iterator not dereferencable 問題 include stdafx.h include include using namespace std 遞迴求和函式 int sum1 int value...

遞迴執行上下文和堆疊

我們接著昨天的遞迴繼續講述關於遞迴的執行上下文,以及堆疊。現在,讓我們檢查一下遞迴呼叫是如何工作的。為此,我們將深入研究功能。有關正在執行的功能的執行過程的資訊儲存在其執行上下文中。執行上下文是乙個內部資料結構,它包含關於函式執行的詳細資訊 控制流現在的位置 當前變數 該變數的值 我們在這裡不使用它...

函式呼叫約定和堆疊

編譯器一般使用堆疊實現函式呼叫。堆疊是儲存器的乙個區域,嵌入式環境有時需要程式設計師自己定義乙個陣列作為堆疊。windows為每個執行緒自動維護乙個堆疊,堆疊的大小可以設定。編譯器使用堆疊來堆放每個函式的引數 區域性變數等資訊。函式呼叫經常是巢狀的,在同一時刻,堆疊中會有多個函式的資訊,每個函式占用...