《資料結構》嚴蔚敏 用棧實現遞迴來解決hanoi問題
阿新 • • 發佈:2019-01-12
感覺書上對遞迴操作的棧理解的挺好的,有需要的可以去找一下書看一下
//hanoi problem #include<stdio.h> #include<stdlib.h> #include<string.h> int times = 1; void move(char from,int n,char to) { printf("%d times: Move disk %d from %c -> %c \n",times++,n,from,to); } int hanoi(int n,char x,char y,char z) { if(n == 1) { move(x,1,z); } else { hanoi(n-1,x,z,y); move(x,n,z); hanoi(n-1,y,x,z); } return times; } int main(int argc, char const *argv[]) { int times ; int n ; char x = 'X',y = 'Y',z = 'Z'; printf("please enter the hanoi blocks: "); while(scanf("%d",&n) == 1) { times = hanoi(n,x,y,z); printf("all move %d times\n",times-1); } return 0; }
非遞迴演算法,即自己構建這麼一個進棧入棧的過程,不過
用Visual Studio除錯的結果,在移動同樣多的盤子情況下,兩種方法消耗的記憶體相差不大,但時間有較大差別,使用迭代的方法花費的時間是遞迴方法的近十倍。原因有以下幾點:
迭代過程中要反覆地動態建立變數,這也是時間開銷差距的主要原因
遞迴過程由於編譯過程對遞迴變數和遞迴函式有很好的優化處理,因而效率較高
迭代程式碼
#include<stdio.h> #include<stdlib.h> #include<string.h> typedef struct record //用於記錄遞迴環境,放入棧中 { int n; char moveFrom; char moveTo; char swap; struct record *next; } record; typedef struct stack //定義一個棧 { record * records; int num; } stack; void push(record *record, stack *stack) //向棧內放置元素 { stack->num++; record->next = stack->records; stack->records = record; } record * pop(stack *stack) //從棧頂彈出元素 { record *record; stack->num--; record = stack->records; stack->records = stack->records->next; return record; } //move方法,實現將n個盤子從moveFrom柱藉助swap柱移動到moveTo柱 void move(int n, char moveFrom, char moveTo, char swap) { stack stack = { NULL, 0 }; record *record1, *p_record; //初始化棧 record1 = (record *)malloc(sizeof(record)); record1->n = n, record1->moveFrom = moveFrom, record1->moveTo = moveTo; record1->swap = swap; push(record1, &stack); //迭代開始 while (stack.num != 0) { //從棧中取出元素,並進行相應操作 p_record = pop(&stack); if (p_record->n == 1) { printf("%c->%c\t", p_record->moveFrom, p_record->moveTo); free(p_record); continue; } //記錄遞迴環境,並放入棧中 record *record2 = (record *)malloc(sizeof(record)); record *record3 = (record *)malloc(sizeof(record)); record *record4 = (record *)malloc(sizeof(record)); record2->n = p_record->n - 1, record2->moveFrom = p_record->moveFrom, record2->moveTo = p_record->swap, record2->swap = p_record->moveTo; record3->n = 1, record3->moveFrom = p_record->moveFrom, record3->moveTo = p_record->moveTo, record3->swap = p_record->swap; record4->n = p_record->n - 1, record4->moveFrom = p_record->swap, record4->moveTo = p_record->moveTo, record4->swap = p_record->moveFrom; push(record4, &stack); push(record3, &stack); push(record2, &stack); //不要忘記釋放記憶體 free(p_record); } } int main() { int n = 3; //呼叫move方法 move(n, 'A', 'B', 'C'); return 0; }