回顧性分析是跟蹤決策的特點之壹。指對原有決策機制、決策內容、主客觀環境等的分析。從出發點、原因、問題性質、錯誤程度等。導致決策失誤的按順序進行調查。
【算法分析】
為了描述壹個問題的狀態,我們必須使用它以前的狀態,為了描述以前的狀態,我們也必須使用它以前的狀態...這種自己定義自己的方法叫做遞歸定義。例如,將函數f(n)定義為:
f(n)= n * f(n-1)(n & gt;0)
f(n)=1 (n=0)
那麽當0時,f(n)必須由f(n-1)定義,f(n-1-1)必須由f(n-1)定義...當n=0時,F (n) = 65438。
從上面的例子中,我們可以看到遞歸定義有兩個元素:
(1)遞歸邊界條件。也就是所描述的問題的最簡單的情況,它本身不再使用遞歸定義。
和上面的例子壹樣,當n=0時,f(n)=1,不用f(n-1)來定義。
(2)遞歸定義:將問題轉化為邊界條件的規則。遞歸定義必須讓問題越來越簡單。
比如f(n)由f(n-1)定義,它越來越接近f(0),也就是邊界條件。最簡單的情況是f(0)=1。
遞歸算法往往效率低下,耗時耗內存。不過遞歸也有它的好處,可以讓壹個有遞歸關系、結構復雜的程序簡介變得簡潔,增加可讀性。特別是在很難找到從邊界到解的全過程的情況下,如果將問題推得更遠,結果仍然保持原問題的關系,那麽用遞歸算法編程更合適。
遞歸分為:1。直接遞歸,遞歸過程P直接調用自己;2.間接遞歸,即P包含另壹個進程D,D調用P .
遞歸算法適用於如下壹般場合:
1.數據是遞歸定義的。
比如Peibonachi序列的定義:f(n)= f(n-1)+f(n-2);f(0)= 1;f(1)=2。
相應的遞歸程序是:
函數fib(n:整數) :整數;
開始
如果n = 0,則fib:= 1 {遞歸邊界}
否則,如果n = 1,則fib := 2
else fib:= fib(n-2)+fib(n-1){ recursive }
結束;
這類遞歸問題可以轉化為遞歸算法,用遞歸邊界作為遞歸邊界條件。
2.數據之間的關系(即數據結構)是遞歸定義的,如樹遍歷、圖搜索等。
3.問題用遞歸算法解決,如回溯法。
從問題的某種可能性出發,搜索從這種情況下可以達到的所有可能性,當這條路走到盡頭的時候。
回到起點,從另壹種可能出發,繼續搜索。這種不斷“回溯”尋找解決方案的方法被稱為
“回溯法”。
[參考程序]
下面給出壹個用回溯法求所有路徑的算法框架。筆記已經寫得很清楚了,請仔細理解。
const max depth =;
type statetype =;{狀態類型定義}
operator type =;{運算符類型定義}
Node =記錄{節點類型}
state:state type;{狀態字段}
operator:operator type {運算符字段}
結束;
{註:節點的數據類型可以根據試題需要進行簡化}
定義變量
堆棧:數組[1..max depth];{保存當前路徑}
合計:整數;{路徑數}
程序make(l:整數);
Var i:整數;
開始
如果堆棧[L-1]是目標節點,那麽。
開始
合計:=合計+1;{路徑數+1}
打印當前路徑[1..l-1];
出口
結束;
對於i := 1到解樹次數do
開始
生成堆棧[l]。操作員;
堆棧[l]。運算符作用於堆棧[l-1]。狀態以生成新的狀態堆棧[l]。狀態;
If stack[l]。狀態滿足約束條件則make(k+1);
{如果不滿足約束條件,將通過for循環更改運算符擴展。}
{遞歸返回那裏時,系統會自動恢復調用前的堆棧指針和操作符,然後通過for循環改變壹個操作符擴展。}
{註意:如果在擴展stack[l]時使用了全局變量。狀態,您應該插入幾個語句來恢復。
堆棧[l-1].狀態時的值。
結束;
{沒有更多可用的運算符,正在回溯}
結束;
開始
總計:= 0;{初始化為0的路徑數}
初始化處理;
make(l);
打印路徑總數
結束。