2011-07-11 08:40:10Morris

鏈結 Stack (堆疊)

原本用遞迴寫堆疊就可以了, 但是有些電腦的遞迴深度一超過某一個限制
馬上就會出現遞迴溢滿, stack overflow
此時手動的 stack 就不得不出現了
做手動的堆疊的時候, 必須將所有的狀態變數, 塞進 stack 的變數中

我不是什麼大牛, 僅僅提供我的寫法
那麼我就給一個範例

int flag, Atop = 0;
char Ans[30001];
void TriePrint(TrieNode *now, int dv) {
    if(now == NULL)    return;
    TrieNode *curr = now->kid;
    if(flag == 1) {
        int a;
        for(a = 0, flag = 0; a < dv; a++)
            Ans[Atop++] = ' ', Ans[Atop++] = ' ', Ans[Atop++] = ' ';
    }
    Ans[Atop++] = '[', Ans[Atop++] = now->c, Ans[Atop++] = ']';
    while(curr != NULL) {
        TriePrint(curr, dv+1);
        curr = curr->peer;
    }
    if(now->kid == NULL)    Ans[Atop] = '\0', puts(Ans), flag = 1, Atop = 0;
}

上面是最原先的程式碼, 在紅色的部分, 你可以很明顯的發現到,
我使用內建的遞迴, 來實踐 stack, 現在需要更改成手動的

typedef struct Stack {
    struct Stack *prev;
    struct TrieNode *now, *curr;   
    int dv;
    char work;
}Stack;

我需要一個 Stack 的結構, 但是我不知道有多深, 因此採用 linked list
struct Stack *prev; //堆疊退回來的時候使用
struct TrieNode *now, *curr; //原本出現在遞迴中的變數, 塞進 stack 變數中
int dv; //原本出現在遞迴中的變數, 塞進 stack 變數中
char work; //工做到哪裡, 遞迴中, 分成遞迴前的宣告 0, 遞迴後的處理 1

void TriePrint(TrieNode *now, int dv) {
    Stack *stack, *temp;
    stack = (Stack*)malloc(sizeof(Stack));
    stack->prev = NULL, stack->now = now, stack->dv = dv, stack->work = 0;
    int a, Atop = 0;
    char Ans[30005], flag, flag2;
    while(stack != NULL) {
        if(stack->work == 0) {           
            if(flag == 1) {
                for(a = 0, flag = 0; a < stack->dv; a++)
                    Ans[Atop++] = ' ', Ans[Atop++] = ' ', Ans[Atop++] = ' ';
            }
            stack->curr = stack->now->kid, stack->work = 1;
            Ans[Atop++] = '[', Ans[Atop++] = stack->now->c, Ans[Atop++] = ']';

        }           
        flag2 = 0;
        while(stack->curr != NULL) {
            temp = (Stack*)malloc(sizeof(Stack));
            temp->now = stack->curr, temp->prev = stack, temp->dv = stack->dv+1;
            temp->work = 0;
            stack->curr = stack->curr->peer;
            stack = temp, flag2 = 1;
            break;
        }
        if(flag2) continue;
        if(stack->now->kid == NULL)    Ans[Atop] = '\0', puts(Ans), flag = 1, Atop = 0;
        temp = stack->prev, free(stack), stack = temp;
    }
}

第一次改寫 遞迴 成 手動 stack
若寫得不好, 請多多見諒