通過上述討論,可以看出遞歸程序在執行時需要系統提供隱式棧這種數據結構來實現,對於 一般的遞歸過程,仿照遞歸算法執行過程中遞歸工作棧的狀態變化可直接寫出相應的非遞歸算法。
這種利用棧消除遞歸過程的步驟如下:
(1)設置一個工作棧存放遞歸工作記錄(包括實參、 返回地址及局部變量等)。
(2)進入非遞歸調用入口(即被調用程序開始處) 將調用程序傳來的實在參數和返回地址入 棧(遞歸程序不可以作爲主程序,因而可認爲初始是被某個調用程序調用。
(3)進入遞歸調用入口:當不滿足遞歸結束條件時,逐層遞歸,將實參、 返回地址及局部變 量入棧,這一過程可用循環語句來實現一模擬遞歸分解的過程。
(4)遞歸結束條件滿足,將到達遞歸出口的給定常數作爲當前的函數值。
(5)返回處理:在棧不空的情況下,反覆退出棧頂記錄,根據記錄中的返回地址進行題意規 定的操作,即逐層計算當前函數值,直至棧空爲止一模擬遞歸求值過程。
通過以上步驟,可將任何遞歸算法改寫成非遞歸算法。但改寫後的非遞歸算法和原來比較起 來,結構不夠清晰,可讀性差,有的還需要經過一系列的優化,這裏不再舉例詳述,具體示例參 見5.5.1節中二叉樹中序遍歷的非遞歸算法。
自己思路:
1、設置棧頂和棧
2、循環條件一般有兩個以上,其中一個棧頂
二叉樹中序遍歷
#include<stdio.h>
#include<stdlib.h>
//棧頂,棧的值
typedef struct tree{
int value;
struct tree *left;
struct tree *right;
}Tree;
void d(Tree *t){
if(t){
d(t->left);
printf("%d\n",t->value);
d(t->right);
}
}
void gas(Tree *tr){
Tree *stack[10];
int i=-1; //棧無值
while(i>=0||tr){ //i+1標誌還有多少個棧
if(tr){
i++;
stack[i]=tr;
tr=tr->left;
}
else{
printf("%d\n",stack[i]->value);
tr=stack[i]->right;
i--;
}
}
return;
}
int main(){
//構建樹,簡便寫法
Tree *head=(Tree *)malloc(sizeof(Tree));
head->value=12;
head->left=NULL;
head->right=NULL;
Tree *a=(Tree *)malloc(sizeof(Tree));
a->value=11;
a->left=NULL;
a->right=NULL;
head->left=a;
Tree *b=(Tree *)malloc(sizeof(Tree));
b->value=10;
b->left=NULL;
b->right=NULL;
head->right=b;
//遞歸算法
// d(head);
//非遞歸算法
gas(head);
return 0;
}