C語(yǔ)言遞歸:漢諾塔問(wèn)題分析
問(wèn)題背景
漢諾塔問(wèn)題源自印度一個(gè)古老的傳說(shuō),印度教的“創(chuàng)造之神”梵天創(chuàng)造世界時(shí)做了 3 根金剛石柱,其中的一根柱子上按照從小到大的順序摞著 64 個(gè)黃金圓盤(pán)。梵天命令一個(gè)叫婆羅門(mén)的門(mén)徒將所有的圓盤(pán)移動(dòng)到另一個(gè)柱子上,移動(dòng)過(guò)程中必須遵守以下規(guī)則:
每次只能移動(dòng)柱子最頂端的一個(gè)圓盤(pán);每個(gè)柱子上,小圓盤(pán)永遠(yuǎn)要位于大圓盤(pán)之上;
游戲體驗(yàn)
點(diǎn)擊開(kāi)始體驗(yàn)游戲:??漢諾塔游戲 (gitee.io)??

漢諾塔移動(dòng)次數(shù)規(guī)律
個(gè)數(shù) | 移動(dòng)次數(shù)f(n) | 規(guī)律 |
1 | 1 | 2^1-1 |
2 | 3 | 2^2-1 |
3 | 7 | 2^3-164-1 |
4 | 15 | 2 |
... | ... | ... |
n | 2^n-1 | 2^n-1 |
由上述分析可以得到f(n)與f(n-1)的關(guān)系:
所以:f(n)=2^n-1 ; f(n-1)=2^(n-1)-1
f(n)=2^n-1=2^1*(2^(n-1)-1)+1=2*f(n-1)+1
移動(dòng)過(guò)程的深層解讀
漢諾塔問(wèn)題的三步過(guò)程歸納
(我們是把n-1個(gè)圓盤(pán)看成一個(gè)整體去分析的)
一.把n-1個(gè)圓盤(pán)從A(經(jīng)過(guò)C)移到B

二. 把A上第n個(gè)圓盤(pán)移到C

三: 把B上的(n-1)個(gè)圓盤(pán)(經(jīng)過(guò)A)移到C

重點(diǎn)?。。?!
中間的一步是把最大的一個(gè)盤(pán)子由A移到C上去;A->C
(1)中間一步之前可以看成把A上n-1個(gè)盤(pán)子通過(guò)借助C塔移到了B上,A->B
(2)中間一步之后可以看成把B上n-1個(gè)盤(pán)子通過(guò)借助A塔移到了C上;B->C
圖解:
階數(shù) | 步驟 |
1 | A->C |
2 | A->B,A->C,B->C |
3 | A->C,A->B,C->B,A->C,B->A,B->C,A->C |
4 | A->B,A->C,B->C,A->B,C->A,C->B,A->B,A->C,B->C,B->A,C->A,B->C,A->B,A->C,B->C |
... | ... |
奇數(shù) | 第一步A->C |
偶數(shù) | 第一步A->B |
發(fā)現(xiàn):
奇數(shù)個(gè)圓盤(pán)第一步永遠(yuǎn)為A–>C
偶數(shù)個(gè)圓盤(pán)第一步永遠(yuǎn)為A–>B
代碼實(shí)現(xiàn)1
僅打印移動(dòng)次數(shù)
#include<stdio.h>
int Tower(int num)
{
if(num==1)
return 1;
else
return 2*Tower(num-1)+1;
}
int main()
{
int num=0;
int ret=0;
printf("請(qǐng)輸入層數(shù):");
scanf("%d",&num);
ret=Tower(num);
printf("需要%d次完成\n",ret);
return 0;
}關(guān)鍵步驟
if(num==1) return 1; else return 2*Tower(num-1)+1;

代碼實(shí)現(xiàn)2
打印移動(dòng)的具體過(guò)程
#include <stdio.h>
void Move(char A,char C)
{
printf("%c --> %c\n",A,C);
}
void tower(int a,char A,char B,char C)//漢諾塔函數(shù)實(shí)施主體,A為初始柱,B為經(jīng)由柱,C為目的柱
{
if (a==1)
{
Move(A,C);
}
else
{
tower(a-1,A,C,B);//把n-1個(gè)圓盤(pán)從A(經(jīng)過(guò)C)移到B
Move(A,C);
tower(a-1,B,A,C);//把B桿上的(n-1)個(gè)圓盤(pán)(經(jīng)過(guò)A)移到C
}
}
int Tower(int num)
{
if (num==1)
return 1;
else
return 2*Tower(num-1)+1;
}
int main()
{
int a = 0;
int Num=0;
printf("請(qǐng)輸入層數(shù):");
scanf("%d",&a);
Num = Tower(a);
printf("%d層需要移動(dòng)%d步\n", a, Num);
tower(a, 'A', 'B', 'C');//進(jìn)入遞歸
return 0;
}
補(bǔ)充
進(jìn)階題:移動(dòng)盤(pán)子的過(guò)程中只能夠相鄰柱間移動(dòng),結(jié)論:移動(dòng)次數(shù):f(n)=3^n-1
到此這篇關(guān)于C語(yǔ)言遞歸:漢諾塔問(wèn)題分析的文章就介紹到這了,更多相關(guān)遞歸:漢諾塔問(wèn)題內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C語(yǔ)言實(shí)現(xiàn)簡(jiǎn)單計(jì)算器程序
這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言實(shí)現(xiàn)簡(jiǎn)單計(jì)算器程序,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-02-02
C語(yǔ)言實(shí)現(xiàn)簡(jiǎn)單的貪吃蛇游戲
這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言實(shí)現(xiàn)簡(jiǎn)單的貪吃蛇游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-07-07
C語(yǔ)言編程數(shù)據(jù)結(jié)構(gòu)的棧和隊(duì)列
本篇文章是C語(yǔ)言編程篇,主要為大家介紹C語(yǔ)言編程中的數(shù)據(jù)結(jié)構(gòu),詳細(xì)的講解了數(shù)據(jù)結(jié)構(gòu)的棧和隊(duì)列有需要的朋友可以借鑒參考下,希望可以有所幫助2021-09-09
C++ 如何將string轉(zhuǎn)換成全小寫(xiě)
這篇文章主要介紹了C++ 如何將string轉(zhuǎn)換成全小寫(xiě)問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。2022-11-11

