递归算法——汉诺塔问题
一年前,老師用斐波那契數(shù)列引領(lǐng)我走進(jìn)遞歸的殿堂,同一天,用漢諾塔扼殺了我對遞歸的好感。。。。。。
今天翻開算法書本來想看看有哪些經(jīng)典問題被遺漏時(shí),看到了這個(gè)漢諾塔,我才想起來當(dāng)初老師講這個(gè)問題的時(shí)候我沒聽懂,問題被擱置了,今天看見我才想起來,對于現(xiàn)在的我肯定沒什么挑戰(zhàn),但是當(dāng)初剛學(xué)遞歸的時(shí)候,真被它弄傻了。
看一下題目吧:
總的來說就是最終將所有圓盤都移動到c上面。移動過程中大圓盤不能在小圓盤上面,每次只能移動一個(gè)圓盤。
思考一下,將所有圓盤都移動到c上面,那么肯定需要將[1,n-1]圓盤都移動到b上面,然后a上的最大的圓盤n移動到c上面;然后的問題就變成了將[1,n-1]圓盤從b上借助a移動到c上面。
如果說void Hanoi(int n, char x, char y, char z)是我們的函數(shù),表示將n個(gè)圓盤從x上借助y移動到z上面。那么我們肯定是按照剛才分析的,
(1)一開始調(diào)用該函數(shù)是Hanoi(n, a, b, c)表示將n個(gè)圓盤從a上借助b移動到c上。
(2)如果我們完成步驟(1)必須完成先將[1,n-1]圓盤從a上借助c移動到b上(因?yàn)橹挥羞@樣,n圓盤才能從a拿到到c上),調(diào)用函數(shù)就是Hanoi(n-1,a,c,b),表示將[1,n-1]圓盤從a上借助c移動到b上。
(3)完成步驟1之后,我們要做的就是將b上的[1,n-1]圓盤從b上借助a移動到c上。這個(gè)和起初問題一模一樣,只不過起初問題是從a借助b移動到c,現(xiàn)在是從b借助a移動到c。
看代碼:
首先我們肯定希望n個(gè)圓盤從a上借助b,移動到c上
剩下的就是Hanoi這個(gè)函數(shù)了。如果我們要完成將n個(gè)圓盤從x上借助y移動到z上,那么肯定需要從x上借助z,將[1,n-1]這些圓盤移動到y(tǒng)上,如下步驟②;移動過后,我們需要將n圓盤從x上拿到z上,如下步驟③;然后,我們需要將b上的[1,n-2]圓盤從y上借助x移動到z,如下步驟④后面就是重復(fù)步驟了。注意遞歸出口,當(dāng)Hanoi中的n為0時(shí),返回。
void Hanoi(int n, char x, char y, char z)//注意這個(gè)n是表示n個(gè)圓盤 {if(n == 0) return;Hanoi(n-1, x, z, y);//步驟②move(n, x, z);//步驟③ 注意這個(gè)n是表示第n個(gè)圓盤Hanoi(n-1, y, x, z);//步驟④ }還剩一個(gè)move函數(shù)沒寫,move函數(shù)就是簡單的將一個(gè)圓盤從一個(gè)柱子上面移動到另一個(gè)柱子上面而已。
void move(int n, char src, char tar) {printf("將%d從%c移動到%c:%c->%c\n", n, src, tar, src, tar); }綜合代碼:
int g_num = 1;void move(int n, char src, char tar) {printf("第%d步:將%d從%c移動到%c:%c->%c\n", g_num++, n, src, tar, src, tar); }void Hanoi(int n, char x, char y, char z)//注意這個(gè)n是表示n個(gè)圓盤 {if (n == 0) return;Hanoi(n - 1, x, z, y);//步驟②move(n, x, z);//步驟③ 注意這個(gè)n是表示第n個(gè)圓盤Hanoi(n - 1, y, x, z);//步驟④ }int main() {Hanoi(3, 'a', 'b', 'c');//①這個(gè)調(diào)用表示我們想要將n個(gè)圓盤從a上借助b移動到c上return 0; }運(yùn)行結(jié)果;
總結(jié)
以上是生活随笔為你收集整理的递归算法——汉诺塔问题的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 设计模式——单例模式(懒汉模式,饿汉模式
- 下一篇: 计算机网络——HTTP协议和Web