資料結構 演算法 14 遞迴 轉非遞迴

2022-09-22 04:33:09 字數 1360 閱讀 6094

目錄遞迴**改為非遞迴**

遞迴是一種應用非常廣泛的演算法、程式設計技巧,如:

所有的遞迴都可以轉為非遞迴實現。

李柱明部落格:

遞迴的定義:

遞迴與棧結構:

優點:遞迴**的表達力很強,寫起來非常簡潔。

缺點:空間複雜度高。

有堆疊溢位的風險。

存在重複計算。

過多的函式呼叫會耗時較多。

遞迴需要滿足的兩個條件:

乙個問題可以分解為 n 個子問題。且子問題與原問題有著相同的形式。

存在遞迴終止條件。

編寫遞迴**的方法 1:

寫出遞推公式。

找到終止條件。

如中序遍歷:

遞推公式,左中右:in_order(c) = in_order(c_left) -> print c -> in_order(c_right)

終止條件:要遍歷的結點為空。即是傳進來的引數為空。

例子:假如這裡有 n 個台階,每次你可以跨 1 個台階或者 2 個台階,請問走這 n 個台階有多少種走法?

分析:

int f(int n)

編寫遞迴**的關鍵是,只要遇到遞迴,我們就把它抽象成乙個遞推公式,不用想一層層的呼叫關係,不要試圖用人腦去分解遞迴的每個步驟

遞迴使用的是系統堆疊,如果系統堆疊溢位會造成系統性崩潰。

避免遞迴堆疊溢位方法:

限制遞迴深度。(採用全域性或者靜態變數記錄遞迴深度)

上面 f(3)就重複計算了,其實沒必要。

可以記錄每個 f(x) 的結果。在遞迴過程時優先遍歷這些結果,如果沒有直接結果才計算。

儲存 f(x) 的結果的資料結構有很多種,如雜湊表、鍊錶、樹等等。

所有的遞迴**都可以改為迭代迴圈的非遞迴寫法。

非遞迴方法思路:因為遞迴是借助棧來實現的,所以:

遞迴中發生變化的變數(遞迴返回值)-> 迴圈中每一次處理完相應變數存入 stack 中(push 進棧)。

遞迴中使用遞迴返回值 -> 迴圈中取出 stack 中的值進行處理(pop 出棧)。

既然入棧又出棧,那直接使用乙個固定空間,如函式棧,即是使用變數來儲存該值。

一般從尾遞迴開始反過來迭代迴圈。意思是迭代迴圈是迴圈遞迴**棧的流程

如台階**:

int f(int n)

return ret;

}

資料結構 非遞迴

include stdafx.h include using namespace std 二叉樹鏈式儲存的標頭檔案 typedef char datatype 結點屬性值型別 typedef struct node 二叉樹結點的型別 bintnode typedef bintnode bintree...

遞迴轉非遞迴

題目描述 給定乙個列表,該列表中的每個要素要麼是個列表,要麼是整數。將其變成乙個只包含整數的簡單列表。如果給定的列表中的要素本身也是乙個列表,那麼它也可以包含列表。您在真實的面試中是否遇到過這個題?樣例給定 1,2,1,2 返回 1,2,1,2 給定 4,3,2,1 返回 4,3,2,1 挑戰請用非...

資料結構 演算法 遞迴

遞迴在較為高階的數演算法實現中是常用的,比如深度優先搜尋,暴力搜尋。下面展示較為簡單的遞迴 執行的過程中。public void recurisve recurisve system.out.println str test public void test 測試 依次輸入是 k i h a 依次輸...