c語言遞歸漢諾塔
㈠ c語言漢諾塔程序
將以下內容全部復制到新建的源文件中:(本人自己寫的,因為你那課本上的代碼,沒解釋,書寫不規范,很難理解清楚,所以我直接新寫了一個完整的代碼,附帶詳細說明)
#include <stdio.h>
//漢諾塔x層塔從A塔整體搬到C塔,中間臨時B塔。
//x層塔是從大到小往上疊放。每次移動只能移動一層塔。並且在移動過程中必須保證小層在上邊
//藉助B塔可以將x層塔全部從A搬到C上,並且符合要求(在移動過程中大的那塊在下邊,小的那塊在上邊)
int main()
{
void tower(int x,char a,char b,char c); //聲明函數
int x=5,a='A',b='B',c='C'; //x表示有5層塔,具體要多少層自己修改這個值。abc分別表示ABC塔。
tower(x,a,b,c); //x層塔從a移動到c的全過程,主程序只有這條有效語句
return 0;
}
//以下是tower函數的定義
//參數解析:x層塔放在a上,b是中間塔,c是目標塔。即x層塔要從a搬到c上。
//此函數實現x層塔從a整體轉移到c上。以及這個過程是怎麼搬的全部過程。
void tower(int x,char a,char b,char c)
{
if(x==1)printf("將%d從%c放到%c\n",x,a,c); //只有1層塔時,直接從a搬到c上。
else //不止1層塔,則先將x-1層塔從a按照規律搬到b上,再將最後一塊從a搬到c上,最後再將b上的x-1層塔按照規律搬到c上。
{
tower(x-1,a,c,b); //先將x-1層塔從a按照規律搬到b上,注意參數b放在最後,因為放在最後的參數是准備搬過去的目標塔。
printf("將%d從%c放到%c\n",x,a,c); //將最後一塊從a搬到c上
tower(x-1,b,a,c); //最後再將b上的x-1層塔按照規律搬到c上,注意參數b放在開頭,因為x-1層是要從b上搬過去的。
}
}
㈡ 求C漢諾塔遞歸過程詳解
解決漢諾塔的基本思想是先把n個盤子除了最下面的盤子以外的所有盤子從第一根柱子(初始柱子)移動到中間那個柱子上(輔助柱子),然後把最下面的盤子移動到最後一根柱子上(目標柱子)。最後把剩下的盤子移動到目標柱子上。這樣,然而,完成第一步和第三步也同樣是一個移動n-1個盤子的漢諾塔問題。於是,遞歸調用在這里不可避免。程序你已經寫的很清楚,給你解釋一下。現把你的程序畫上行以便說明。
1 #include "stdio.h"
2 main()
3 {void hanoi(int,char,char,char); <br/>4 int m; <br/>5 printf("input the number of disks:"); <br/>6 scanf("%d",&m); <br/>7 printf("The step to moving %d disks:\n",m); <br/>8 hanoi(m,'A','B','C'); <br/>9 }
10 void hanoi(int n,char a,char b,char c)
11 {//void move(char,char);
12 if(n==1) move(a,c);
13 else
14 {hanoi(n-1,a,c,b); <br/>15 move(a,c); <br/>16 hanoi(n-1,b,a,c); <br/>17 }
18 }
19 void move(char x,char y)
20 {printf("%c-->%c\n",x,y); <br/>21 }
當m=4時,程序走到第8行,調用函數hanoi(int n,char a,char b,char c)。此時,實參把值傳遞給了形參,於是此時,n=4,a=A,b=B,c=C。我把第11行的void move(char,char); 注釋掉了,應該知道這一句的意思。因為這一行雖然可以讓程序更加完整,但是解釋的時候加上它會很麻煩。程序走到第12行,因為此時n=4,而不等於1,程序直接走第13行。於是調用第14行的hanoi(n-1,a,c,b)。這是一個遞歸調用。此時,n=3,a=A,c=B,b=C。要清楚,A,B,C代表的意義。A代表初始柱子,B代表輔助柱子,C代表目標柱子。而a代表第一根柱子,b代表第二根柱子,c代表第三根柱子。這是不一樣的。程序繼續走,到12行時n依然不等於1。走到14行調用hanoi(n-1,a,c,b)。此時,n=2,a=A,c=C,b=B。程序再走,到12行時n依然不等於1,走到14行調用hanoi(n-1,a,c,b)。此時,n=1,a=A,c=B,b=C。程序走到12行時發現n=1,程序開始走15行。調用move(char x,char y)到20行時輸出A-->B。調用結束,回到上一個調用即n=2,a=A,c=C,b=B。程序回到第15行,輸出 A-->B。再走第16行,調用hanoi(n-1,b,a,c)。此時n=1,b=A,a=B,c=C。程序回到12行再調用19行輸出B-->C。調用結束,回到上一個調用n=3,a=A,c=B,b=C。程序走到15行,輸出A-->C,這時,第一根柱子上有一個盤子,第二根柱子上有一個盤子,第三根柱子上有兩個盤子。再調用16行就可以完成把第三根柱子里的所有盤子都移動到第二根柱子上。這樣。我們就完成了整體目標的第一步。把n個盤子除了最下面的盤子以外的所有盤子從第一根柱子(初始柱子)移動到中間那個柱子上(輔助柱子),調用完成後程序回到15行,此時n=3,a=A,c=B,b=C。15行時輸出A-->C,這時便完成了整體目標的第二步,最下面的盤子移動到最後一根柱子上(目標柱子)。再根據程序走到16行,經過跟14行類似的一系列的遞歸調用,我們就可以完成最終目標了。
㈢ c語言遞歸調用漢諾塔
首先調用 hanoi(3,a,b,c)
判斷 「3」是否為「1」
不為「1」
{
{ 調用 hanoi(n-1, one, three, two),即hanoi(2,a,c,b)
執行hanoi(2,a,c,b),此時 one = a,two = c,thtee = b;
判斷 「2」是否為「1」,不為1
調用 hanoi(n-1, one, three, two),即hanoi(1,a,b,c)
執行hanoi(1,a,b,c),此時 one = a,two = b,thtee = c;
判斷 「1」是否為「1」,為1,執行move(one, three)即move(a, c)
以上為循環執行hanoi(n-1, one, three, two)函數,直到「n==1」
}
執行move(one, three);
執行hanoi(n-1, two, one, three)
{
循環執行hanoi(n-1, two, one, three),直到「n==1」
}
}
主要是遞歸的用法
好像解釋的不太清楚,但希望能幫到你。
㈣ 求大神講解一下C語言漢諾塔遞歸演算法的簡易理解
一開始我接觸漢諾塔也是很不解,隨著代碼量的積累,現在很容易就看懂了,因此樓主主要還是對遞歸函數的理解不夠深刻,建議你多寫一些遞歸程序,熟練了自己就能理解。
圓盤邏輯移動過程+程序遞歸過程分析
hanoi塔問題, 演算法分析如下,設a上有n個盤子,為了便於理解我將n個盤子從上到下編號1-n,標記為盤子1,盤子2......盤子n。
如果n=1,則將「 圓盤1 」 從 a 直接移動到 c。
如果n=2,則:
(1)將a上的n-1(等於1)個圓盤移到b上,也就是把盤1移動到b上;
(2)再將a上 「盤2」 移到c上;
(3)最後將b上的n-1(等於1)個圓盤移到c上,也就是第(1)步中放在b上的盤1移動到c上。
注意:在這里由於超過了1個盤子,因此不能直接把盤子從a移動到c上,要藉助b,那
么 hanoi(n,one,two,three)的含義就是由n個盤子,從one移動到three,如果n>2
那麼就進行遞歸,如果n=1,那麼就直接移動。
具體流程:
hanoi(2,a,b,c);由於2>1因此進入了遞歸的環節中。
<1>執行hanoi(1,a,c,b):這里就是剛才的步驟(1),代表藉助c柱子,將a柱子上的 1個圓盤(盤1)移動到b柱子,其實由於是n=1,此時c柱子並沒被用到,而是直接移動了。
<2>執行hanoi(1,a,b,c):這是步驟(2),藉助b柱子,將a柱子上的一個圓盤(盤2)移動到c柱子上。這里由於也是n=1,也並沒有真正藉助b柱子,直接移動的。
<3>執行hanoi(1,b,a,c):這是步驟(3),將b上的一個盤子(盤1)移動到c
函數中由於每次調用hanoi的n值都是1,那麼都不會進入遞歸中,都是直接執行了mov移動函數。
如果n=3,則:(倒著想會想明白)移動的倒數第二部,必然是下面的情況
(1)將a上的n`-1(等於2)個圓盤移到c上,也就是將盤1、盤2 此時都在b柱子上,只有這樣才能移動最下面的盤子(盤3)。那麼由於現在我們先忽略的最大的盤子(盤3),那麼我們現在的目標就是,將兩個盤子(盤1、盤2)從a柱子上,藉助c柱 子,移動到b柱子上來,這個過程是上面n=2的時候的移動過程,n=2的移動過程是「2 個盤子,從柱子a,藉助柱子b,移動到柱子c」。現在是「2個盤子,從柱子a,藉助柱子 c,移動到柱子b上」。因此移動過程直接調用n=2的移動過程就能實現。
(2)將a上的一個圓盤(盤3)移到c。
(3)到這一步,由於已經將最大的盤子(盤3)移動到了目的地,此時無論後面怎麼移動都不需要在用到最大的那個盤子(盤3),我們就先忽略他,剩下的目標就是將b上面的n-1個盤子(盤1、盤2)移動到c上,由於a上沒有盤子了,此時要完成上面的目標,就要藉助a盤子。最終達到的目標就是將b上的2個盤子,藉助a移動到c上,這個過程就是當n=2時分析的過程了,僅僅是最開始的柱子(b柱子)和被藉助的柱子(a柱子)不同了。所以直接調用n=2時候的過程就能股實現了。
具體執行過程:
hanoi(3,a,b,c);由於3>1因此進入了遞歸的環節中。
<1>執行hanoi(2,a,c,b):這里代表剛才的步驟(1),將兩個盤子(盤1、盤2)從a移動到b,中間藉助c。根據n=2的分析過程,必然是能夠達到我們的目的。
<2>執行hanoi(1,a,b,c):現在a上只有一個盤子(盤3),直接移動到c上面即可。
<3>執行hanoi(2,b,a,c):此時對應步驟(3),剩下的目標就是將b上的兩個盤子,藉助a移動到c上。那麼同樣根據n=2的移動過程,必然能達到目的。
最終實現了3個盤子從a,藉助b移動到了c。
㈤ C語言函數遞歸調用漢諾塔問題
我一步步的給你講,就會懂啦:
首先hanoi函數如果把當中的move函數給去掉,就變成了:
voidhanoi(intn,charone,chartwo,charthree)
{
if(n==1)
printf("%c->%c ",one,three);
else
{
hanoi(n-1,one,three,two);
printf("%c->%c ",one,three);
hanoi(n-1,two,one,three);
}
}
也就是把move(one,three),變成了printf("%c->%c ", one, three);。少了一個函數,更加清晰
所以這里的hanoi函數就有了執行的內容:printf
下面以3個盤子為例進行模擬計算機的執行過程:
1、hanoi(3,A,B,C),開始了這步,進入第一層函數,計算機在函數中會進行自我的再次調用(第7行代碼)
2、(第7行):hanoi(2,A,C,B),於是這又是一個新的hanoi函數,這里我把它成為第二層函數
同樣執行到第7行,卡住了,再次一次自我的調用
3、(進入第三層函數):hanoi(1,A,B,C),這里的第三層n=1,所以在第四行就顯示出了"A->C",至此,第三層函數結束,回到調用他的第二層函數
4、在第二層當中,繼續第8行的內容,所以顯示出"A->B",繼續運行,到第9行,開始了有一次自我調用
5、把她稱為貳號第三層函數吧。。。hanoi(1,B,A,C),和第3步類似,這一層函數顯示出了"B->C",然後結束函數,返回調用它的第二層函數
6、第二層函數執行完畢,返回調用它的第一層函數
7、第一層函數中執行到第8行,顯示出"A->C",然後執行第9行:hanoi(2,B,A,C)
............
如果看到了這里理清楚了關系就會懂啦,接下來還有一半,如果都寫下來就太復雜了-。-
你所說的空函數是指沒有返回值,但是這里利用的是電腦調用函數的那種關系來解決的問題,比如上面的3步,會自動返回到第二層函數並繼續
還可以這樣理解漢諾塔,漢諾塔其實是將復雜的問題簡單化,
先不管他有多少個盤子從A到C,我只把它視作3步
就像上面那樣找個例子,反復的按照代碼模擬計算機運行,過個五次六次,就會懂啦
㈥ c語言用遞歸實現漢諾塔
見代碼注釋,還有不懂可以問。
#include<stdio.h>
voidmove(charx,chary)
{
printf("%c-->%c ",x,y);
}
//hannuota函數的作用:把n個圓盤從one柱子藉助two柱子放到three柱子
voidhannuota(intn,charone,chartwo,charthree)
{
if(n==1)//如果只有一個柱子
move(one,three);//直接移動即可
else
{
hannuota(n-1,one,three,two);//先把one柱子上的n-1個圓盤藉助three柱子移動到柱子two
move(one,three);//把第一個柱子的剩下那一個(第n個)移動到第三個柱子
//由於原來one柱子上的n-1個圓盤已經移動到了two柱子上,因此不會有圓盤擋住n圓盤出來
hannuota(n-1,two,one,three);
//最後再把那n-1個圓盤從two柱子藉助one柱子移動到three柱子
//(上面第一句話hannuota(n-1,one,three,two)已經移動到了two柱子,因此這里是從two柱子移動到three柱子)
}
}
intmain()
{
intm;
printf("inputthenumberofdiskes:");
scanf("%d",&m);
printf("Thesteptomove%ddiskes: ",m);
hannuota(m,'A','B','C');
return0;
}
㈦ 漢諾塔n=4(4個盤)c語言遞歸編程代碼
/****************************
漢諾塔的演算法就3個步驟:
第一,把a上的n-1個盤通過c移動到b。
第二,把a上的最下面的盤移到c。a成了空的。
第三,因為n-1個盤全在b上了,所以把b當做a.
重復以上步驟就好了。所以演算法看起來就簡單多了。
******************************/
#include<stdio.h>
staticintm=0;
voidmove(intn,chara,charb,charc)
{
if(n==1)
{
m++;
printf("第%d次移動: ",m);
printf(" %c->%c ",a,c);//當n只有1個的時候直接從a移動到c
}
else
{
move(n-1,a,c,b);//第n-1個要從a通過c移動到b
m++;
printf("第%d次移動: ",m);
printf(" %c->%c ",a,c);
move(n-1,b,a,c);//n-1個移動過來之後b變開始盤,b通過a移動到c,這邊很難理解
}
}
intmain()
{
intn=4;
//printf("請輸入要移動的塊數:");
//scanf("%d",&n);
move(n,'a','b','c');
return0;
}
㈧ 求C語言漢諾塔源碼(遞歸和非遞歸都要)
遞歸演算法是我前些天寫的,非遞歸是剛才找的,裡面含遞歸和非遞歸。\x0d\x0a遞歸演算法:\x0d\x0a#include \x0d\x0a//遞歸求漢諾塔問題\x0d\x0avoid hanoi(int n, char A, char B, char C, int *time)\x0d\x0a{\x0d\x0aif (n>=1)\x0d\x0a{\x0d\x0a hanoi(n-1, A, C, B, time);\x0d\x0a move(A, C);\x0d\x0a (*time)++;\x0d\x0a hanoi(n-1, B, A, C, time);\x0d\x0a }\x0d\x0a}\x0d\x0a//列印出每一步的路徑\x0d\x0avoid move(char a, char c)\x0d\x0a{\x0d\x0aprintf(" %c-->%c\n", a, c);\x0d\x0a}\x0d\x0a\x0d\x0aint main(void)\x0d\x0a{\x0d\x0aint n, time = 0;;\x0d\x0aprintf("請輸入漢諾塔的盤數:");\x0d\x0ascanf("%d", &n);\x0d\x0aprintf("%d個盤的漢諾塔移動方法是:", n);\x0d\x0aprintf("\n");\x0d\x0ahanoi(n, 'A', 'B', 'C', &time);\x0d\x0aprintf("移動了%d次\n", time);\x0d\x0asystem("pause");\x0d\x0areturn 0;\x0d\x0a}\x0d\x0a\x0d\x0a非遞歸演算法:\x0d\x0a#include \x0d\x0a\x0d\x0a#define MAXSTACK 10 /* 棧的最大深度 */\x0d\x0a\x0d\x0aint c = 1; /* 一個全局變數,表示目前移動的步數 */\x0d\x0a\x0d\x0astruct hanoi { /* 存儲漢諾塔的結構,包括盤的數目和三個盤的名稱 */\x0d\x0aint n;\x0d\x0achar x, y, z;\x0d\x0a};\x0d\x0a\x0d\x0avoid move(char x, int n, char y) /* 移動函數,表示把某個盤從某根針移動到另一根針 */\x0d\x0a{\x0d\x0aprintf("%d-> %d from %c -> %c\n", c++, n, x, y);\x0d\x0a}\x0d\x0a\x0d\x0avoid hanoi(int n, char x, char y, char z) /* 漢諾塔的遞歸演算法 */\x0d\x0a{\x0d\x0aif (1 == n)\x0d\x0amove(x, 1, z);\x0d\x0aelse {\x0d\x0ahanoi(n - 1, x, z, y);\x0d\x0amove(x, n, z);\x0d\x0ahanoi(n - 1, y, x, z);\x0d\x0a}\x0d\x0a}\x0d\x0a\x0d\x0avoid push(struct hanoi *p, int top, char x, char y, char z,int n)\x0d\x0a{\x0d\x0ap[top+1].n = n - 1;\x0d\x0ap[top+1].x = x;\x0d\x0ap[top+1].y = y;\x0d\x0ap[top+1].z = z;\x0d\x0a}\x0d\x0a\x0d\x0avoid unreverse_hanoi(struct hanoi *p) /* 漢諾塔的非遞歸演算法 */\x0d\x0a{\x0d\x0aint top = 0;\x0d\x0a\x0d\x0awhile (top >= 0) {\x0d\x0awhile (p[top].n > 1) { /* 向左走到盡頭 */\x0d\x0a push(p, top, p[top].x, p[top].z, p[top].y, p[top].n);\x0d\x0a top++;\x0d\x0a}\x0d\x0aif (p[top].n == 1) { /* 葉子結點 */\x0d\x0a move(p[top].x, 1, p[top].z);\x0d\x0a top--;\x0d\x0a}\x0d\x0aif (top >= 0) { /* 向右走一步 */\x0d\x0a move(p[top].x, p[top].n, p[top].z);\x0d\x0a top--;\x0d\x0a push(p, top, p[top+1].y, p[top+1].x, p[top+1].z, p[top+1].n);\x0d\x0a top++;\x0d\x0a}\x0d\x0a}\x0d\x0a}\x0d\x0a\x0d\x0aint main(void)\x0d\x0a{\x0d\x0aint i;\x0d\x0aprintf("遞歸:\n");\x0d\x0ahanoi(3, 'x', 'y', 'z');\x0d\x0aprintf("非遞歸:\n");\x0d\x0astruct hanoi p[MAXSTACK];\x0d\x0ac = 1;\x0d\x0ap[0].n = 3;\x0d\x0ap[0].x = 'x', p[0].y = 'y', p[0].z = 'z';\x0d\x0aunreverse_hanoi(p);\x0d\x0a\x0d\x0areturn 0;\x0d\x0a}