1. 程式人生 > >c語言實現漢諾塔(程式執行步驟詳解)

c語言實現漢諾塔(程式執行步驟詳解)

很久沒去接觸c語言了,今天翻了翻c語言的書,偶然間看到了大一時讓我鬱悶了很久的漢諾塔問題,又重新推理了一遍,漢諾塔的實現採用遞迴演算法,涉及到資料結構中的棧的知識。下面是c實現漢諾塔的原始碼。程式只是實現了文字資訊,即用文字描述了圓盤的移動過程,並未真正實現圓盤的移動,該程式難度並不大,要了解遞迴的原理和方法中引數值的變化。

# include <stdio.h>

void hannuota(int n,char one,char two,char three);
void move(char x,char y);

int main(void) {
 int n;
 
 printf("please input a  integer number:");
 scanf("%d",&n);

 if(n > 10 || n < 0) {
  printf("請輸入一個0~10範圍內的整數!!");
  return 0;
 }

 hannuota(n,'A','B','C');

 return 0;
}

void hannuota(int n,char one,char two,char three) {
     if(n == 1) {
       move(one,three);   //<1>
    }
   else {
  hannuota((n-1),one,three,two);    //<2>
  move(one,three);                          //<3>


  hannuota((n-1),two,one,three);   //<4>
 }


}

void move(char x,char y) {
 printf("%c ----> %c\n",x,y);
}

為了避免執行需要很長的時間,程式限制了輸入的整數大小為0-10,以下是程式執行的順序:(為了篇幅,假設n的值是3)

main方法執行到hannuota(n,'A','B','C')時;該方法裡的引數為hannuota(3,'A','B','C');

1、第一部分:把A柱中的n-1個圓盤藉助C柱移動到B柱

此時執行hannuota方法,因為n=3>1,因此此時遞迴執行hantuona方法,此時方法引數為hannuota(2,'A','C','B'),(注意此時hannuota方法的引數改變了,C和B值互換);因為n=2>1,繼續遞迴呼叫hannuota(1,'A','B','C');(此時hannuota方法的引數改變了,C和B值互換);因為n=1,所以執行move方法,打印出A-->C

;

返回n=2時程式未執行完的部分,即執行標誌為<3>的move方法,因為此時n=1,打印出A-->B,

繼續執行標誌為<4>的hannuota((n-1),two,one,three)部分,此時引數為hannuota(1,'C','A','B');   此時n=1,打印出C-->B。到此刻位置標誌為<2>部分的 hannuota((n-1),one,three,two)程式執行完畢。

2、第二部分:把A柱的第n個圓盤移動到C盤

此時直接執行標註為<3>部分的程式move(one,three); 此時打印出A-->C;

3、第三部分:把B柱上的n-1個圓盤藉助A移動到C柱

此時執行標誌為<4>部分的hannuota((n-1),two,one,three),此時引數為hannuota(2,'B','A','C');

因為n=2>1,執行標誌為<2>的程式碼,此時方法引數為hannuota(1,'B','C','A');因為此時n=1,執行標誌為<1>的程式碼,打印出B-->A;此時,標誌為<2>的程式執行完畢,one,two,three的值分別為one=B,two=A,three=C;

繼續執行標誌<3>的程式move(one,three); 打印出B-->C; 繼續執行至標誌<4>的程式碼hannuota((n-1),two,one,three),引數為hannuota(1'A','B','C'),因此n=1,執行標誌<1>的程式碼,打印出A-->C;

到此為止,程式執行完畢。

程式執行結果如下:

A ----> C
A ----> B
C ----> B
A ----> C
B ----> A
B ----> C
A ----> C

漢諾塔問題主要分為以上三個部分,程式中用到了遞迴演算法,遞迴要用到棧的知識,就是進棧和出棧,每到遞迴呼叫一個系統的子系統時,都會為子系統分配記憶體單元,把正被呼叫的子系統壓入棧頂,按照先進後出的規則,執行完後就彈出棧,釋放為其分配的記憶體單元。然後繼續執行棧中的其他部分,直到整個程式執行完畢。