Ⅰ 誰給個c語言漢諾塔遞歸演算法及其詳細注釋
源代碼:
#include<stdio.h>
void movedisc(unsigned n,char fromneedle,char toneedle,char usingneedle);
int i=0;
int main()
{
unsigned n;
printf("please enter the number of locomotive:");
scanf("%d",&n); //輸入N值
printf("\tneedle:\t a\t b\t c\n");
movedisc(n,'a','c','b'); //從A上藉助B將N個盤子移動到C上
//*********************************************************************
//在此處加入如下代碼將C上的N個盤子再移回A 去掉此處代碼即漢諾塔問題源代碼
for(int j=1;j<=(int)n;j++)
{
i++;
printf("\t[%d]:\t%2d<-------------%2d\n",i,j,j);
}
//*********************************************************************
printf("\tTotal:\t%d\n",i);
scanf("%d",&n);
return 0;
}
void movedisc(unsigned n,char fromneedle,char toneedle,char usingneedle)
{
if(n>0)
{
//從fromneedle上藉助toneedle將N-1個盤子移動到usingneedle上
movedisc(n-1,fromneedle,usingneedle,toneedle);
++i;
//將fromneedle 上的一個盤子移到toneedle上
switch(fromneedle)
{
case 'a':
switch(toneedle)
{
case 'b':
printf("\t[%d]:\t%2d----->%2d\n",i,n,n);
break;
case 'c':
printf("\t[%d]:\t%2d------------->%2d\n",i,n,n);
break;
}
break;
case 'b':
switch(toneedle)
{
case 'a':
printf("\t[%d]:\t%2d<-----%2d\n",i,n,n);
break;
case 'c':
printf("\t[%d]:\t\t%2d----->%2d\n",i,n,n);
break;
}
break;
case 'c':
switch(toneedle)
{
case 'a':
printf("\t[%d]:\t%2d<-------------%2d\n",i,n,n);
break;
case 'b':
printf("\t[%d]:\t\t%2d<-----%2d\n",i,n,n);
break;
}
break;
}
//從usingneedle上藉助fromneedle將N-1個盤子移動到toneedle上
movedisc(n-1,usingneedle,toneedle,fromneedle);
}
}
Ⅱ 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;
}
Ⅲ 誰能給我講一下,用c語言編寫的漢諾塔程序,是怎麼實現遞歸的啊
我看你是不了解遞歸函數的具體是怎麼實現的,我給你舉一個簡單的例子:就拿階乘來說吧,
我給你把具體實現的過程畫出來
當n=0時,就一步一步返回。這一點很重要。希望對你有幫助。
Ⅳ 求C語言漢諾塔非遞歸演算法
#include#define MAXSTACK 10 /* 棧的最大深度 */int c = 1; /* 一個全局變數,表示目前移動的步數 */struct hanoi { /* 存儲漢諾塔的結構,包括盤的數目和三個盤的名稱 */
int n;
char x, y, z;
};void move(char x, int n, char y) /* 移動函數,表示把某個盤從某根針移動到另一根針 */
{
printf("%d. Move disk %d from %c to %cn", c++, n, x, y);
}void hanoi(int n, char x, char y, char z) /* 漢諾塔的遞歸演算法 */
{
if (1 == n)
move(x, 1, z);
else {
hanoi(n - 1, x, z, y);
move(x, n, z);
hanoi(n - 1, y, x, z);
}
}void push(struct hanoi *p, int top, char x, char y, char z,int n)
{
p[top+1].n = n - 1;
p[top+1].x = x;
p[top+1].y = y;
p[top+1].z = z;
}void unreverse_hanoi(struct hanoi *p) /* 漢諾塔的非遞歸演算法 */
{
int top = 0;while (top >= 0) {
while (p[top].n > 1) { /* 向左走到盡頭 */
push(p, top, p[top].x, p[top].z, p[top].y, p[top].n);
top++;
}
if (p[top].n == 1) { /* 葉子結點 */
move(p[top].x, 1, p[top].z);
top--;
}
if (top >= 0) { /* 向右走一步 */
move(p[top].x, p[top].n, p[top].z);
top--;
push(p, top, p[top+1].y, p[top+1].x, p[top+1].z, p[top+1].n);
top++;
}
}
}int main(void)
{
int i;
printf("reverse program:n");
hanoi(3, 'x', 'y', 'z');
printf("unreverse program:n");
struct hanoi p[MAXSTACK];
c = 1;
p[0].n = 3;
p[0].x = 'x', p[0].y = 'y', p[0].z = 'z';
unreverse_hanoi(p);return 0;
}
Ⅳ 漢諾塔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語言,遞歸漢諾塔問題。求教,詳細些》
遞歸好難啊,參考一下:
#include<stdio.h> /* Copyrighter by SS7E */
void hanoi(int n,char A,char B,char C) /* Copyrighter by SS7E */
{
if(n==1)
{
printf("Move disk %d from %c to %c\n",n,A,C);
}
else
{
hanoi(n-1,A,C,B); /* Copyrighter by SS7E */
printf("Move disk %d from %c to %c\n",n,A,C);
hanoi(n-1,B,A,C); /* Copyrighter by SS7E */
}
}
main() /* Copyrighter by SS7E */
{
int n;
printf("請輸入數字n以解決n階漢諾塔問題:\n");
scanf("%d",&n);
hanoi(n,'A','B','C');
}/* Copyrighter by SS7E */
如果按照最快的速度移動即不重復地移
想移動第二片金片則需要先移動第一片
想移動第三片金片則需要先移動第二片
.
.
.
想移動第64片需要先移動第63片
移動第一片需要1次
移動第二片需要3次(必須將第一片移到第二片上才能將第三片移下來)
移動第三片需要7次
移動第四片需要15次......
可以看出每想移動一片就需要將上邊的所有片摞在一起
所以每移動一片都需要操作上一片次數的二倍+1(自己那片動)
所以由數列可知移動第n片需要2^n-1次
64片就需要2的64次方減1次
2的64次方...
Ⅶ 求大神講解一下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語言遞歸調用漢諾塔
遞歸演算法的出發點不是由初始條件出發,而是把出發點放在求解的目標上,從所求的未知項出發逐次調用本身的求解過程,直到遞歸的邊界(即初始條件)。
漢諾塔問題的重點是分析移動的規則,找到規律和邊界條件。
若需要將n個盤子從A移動到C就需要(1)將n-1個盤子從A移動到B;(2)將你第n個從A移動到C;(3)將n-1個盤子再從B移動到C,這樣就可以完成了。如果n!=1,則需要遞歸調用函數,將A上的其他盤子按照以上的三步繼續移動,直到達到邊界條件n=1為止。
思路清楚了,程序就好理解了。程序中的關鍵是分析好每次調用移動函數時具體的參數和對應的A、B、C塔的對應的關系。下面來以實際的例子對照程序進行說明。
①move(int n,int x,int y,int z)
②{
③ if (n==1)
④ printf("%c-->%c\n",x,z);
⑤ else
⑥ {
⑦ move(n-1,x,z,y);
⑧ printf("%c-->%c\n",x,z);
⑨ {getchar();}//此句有必要用嗎?感覺可以去掉的吧
⑩ move(n-1,y,x,z);
}
}
比如有4個盤子,現在全部放在A塔上。盤子根據編號為1、2、3、4依次半徑曾大。現在要將4個盤子移動到C上,並且是按原順序羅列。首先我們考慮如何才可以將4號移動到C呢?就要以B為中介,首先將上面的三個移動到B。此步的操作也就是程序中的①開始調入move函數(首次調用記為一),當然現在的n=4,然後判斷即③n!=1所以不執行④而是到⑤再次調用move函數(記為二)考慮如何將3個盤移動到B的方法。此處是遞歸的調用所以又一次回到①開始調入move函數,不過對應的參數發生了變化,因為這次要考慮的不是從A移動4個盤到C,而是要考慮從A如何移動移動3個盤到B。因為n=3,故不可以直接移動要藉助C做中介,先考慮將兩個移動到C的方法,故再一次到⑤再一次遞歸調用move函數(記為三)。同理兩個盤還是不可以直接從A移動到C所以要以B為中介考慮將1個移動到B的過程。這次是以B為中介,移動到C為目的的。接下來再一次遞歸調用move函數(記為四),就是移動到B一個,可以直接進行。程序執行③ ④句,程序跳出最內一次的調用(即跳出第四次的調用)返回上一次(第三次),並且從第三次的調用move函數處繼續向下進行即⑧,即將2號移動到了C,然後繼續向下進行到
⑩,再將已經移到B上的哪一個移回C,這樣返回第二次遞歸(以C為中介將3個盤移動到B的那次)。執行⑧,將第三個盤從A移動到B,然後進入⑩,這次的調用時因為是將C上的兩個盤移到B以A為中介,所以還要再一次的遞歸調用,對應的參數傳遞要分析清楚,誰是原塔誰是目標塔,誰是中介塔。過程類似於上面的分析,這里不再重復論述了。
不知道講解清楚了沒有,自己看書時感覺關鍵的地方在於函數參數的傳遞,參數和變數的對應關系對應清楚以後就可以了。
希望對你有所幫助,同時也祝你的問題早日得到解決,呵呵!
Ⅸ c語言遞歸問題: 漢諾塔問題:
//可運行的代碼
#include <stdio.h>
void move(char x,char y) // 定義move函數
{
printf("%c-->%c\n",x,y);
}
void hannuota(int n,char one,char two,char three) // 定義hanuota函數
// 將n個盤從one座藉助two座,移到three座
{
if(n==1)
move(one,three);
else
{
hannuota(n-1,one,three,two);
move(one,three);
hannuota(n-1,two,one,three);
}
}
int main()
{
int m;
printf("input the number of diskes:");
scanf("%d",&m);
printf("The step to move %d diskes:\n",m);
hannuota(m,'A','B','C');
while(1);
return 0;
}
/*
input the number of diskes:3
The step to move 3 diskes:
A-->C
A-->B
C-->B
A-->C
B-->A
B-->C
A-->C
*/