漢諾塔非遞歸實現 C語言版
我上一篇博客是漢諾塔C語言遞歸實現,非遞歸和遞歸想法一樣。這裏不再贅述,直接鏈接轉到:
遞歸實現固然好理解,但是n的值越大,空間和時間上都是極大的消耗,最終可能導致程序直接崩潰。
在以後的做題或者是面試中,不推薦用遞歸方法做,所以要寫出對應的非遞歸方法。
某次上課無意間聽到老師說了這樣一句話:任何遞歸法都可以用循環的方法進行非遞歸實現,然後回頭找了找漢諾塔非遞歸的資料,整理整理,搞出了一個c實現的非遞歸方法
#include<stdio.h>
#include <stdlib.h>
#define MaxSize 100
typedef struct{
int N;
char A; //起始柱
char B; //藉助柱
char C; //目標柱
}ElementType;
typedef struct {
ElementType Data[MaxSize];
int top;
}Stack;//漢諾塔問題的結構類型
void Push(Stack *PtrS, ElementType item){
//入棧操作
if (PtrS->top == MaxSize)
{
printf("The stack is full!\n");
return;
}
else
{
PtrS->Data[++(PtrS->top)] = item;
return;
}
}
ElementType Pop(Stack *PtrS){
if (PtrS->top == -1)
{
printf("The stack is empty!\n");
exit(1); //直接終止程序,一般不會出現這個錯誤
}
else
{
PtrS->top--;
return (PtrS->Data[PtrS->top + 1]); //或者是return PtrS->Data[PtrS->top--];
}
}
//藉助棧的非遞歸實現
void Hanoi(int n){
ElementType P, toPush;
Stack S;
P.N = n; P.A = 'a'; P.B = 'b'; P.C = 'c';
S.top = -1;
Push(&S, P);
while (S.top != -1) //當堆棧不爲空時
{
P = Pop(&S);//出棧
if (P.N == 1)//當只剩一個盤子時,直接由當前柱移動到目的柱
printf("%c -> %c\n", P.A, P.C);
else
{
toPush.N = P.N - 1;
toPush.A = P.B; toPush.B = P.A; toPush.C = P.C;
Push(&S, toPush); //將第三步(n - 1, b, a, c)入棧
toPush.N = 1;
toPush.A = P.A; toPush.B = P.B; toPush.C = P.C;
Push(&S, toPush); //將第二步1, a, b, c)入棧
toPush.N = P.N - 1;
toPush.A = P.A; toPush.B = P.C; toPush.C = P.B;
Push(&S, toPush); //將第一步(n - 1, a, c, b)入棧
}
}
}
int main(){
int n;
scanf("%d", &n);
if (n <= 0)return 0;
else Hanoi(n);
}
還是三個步驟:
1.將n-1個盤子由a柱藉助c柱移動到b柱
2.將最下面的盤子由a柱直接移動到c柱
3.將那n-1個盤子在由b柱藉助a柱移動到c柱
因爲這個是出棧時的操作,所以入棧時要到着寫
簡要解釋一下(因爲跟遞歸思路差不多)
如果n不等於一時,就意味着,以上的n-1個盤子,都要做上述所說的三個步驟,知道n等於1時,直接移動到目的柱。
因此,移動次數最多的是最上邊的那個盤子,移動次數最少的是最下面的那個盤子,只需要移動一次
利用結構體數組更便於理解。
本文爲原創,如有問題歡迎評論區留言。