【數(shù)據(jù)結(jié)構(gòu)】遞歸和分治思想之分治思想

當(dāng)一個(gè)問(wèn)題規(guī)模比較大且不易求解的時(shí)候,就可以考慮將問(wèn)題分成幾個(gè)小的模塊桥氏,逐一求解温峭。
分治思想和遞歸算是有親兄弟的關(guān)系,因?yàn)椴捎梅种嗡枷胩幚韱?wèn)題字支,其各個(gè)小模塊通常具有與大問(wèn)題相同的結(jié)構(gòu)凤藏,這種特性也使遞歸技術(shù)有了用武之地奸忽。

折半查找算法的遞歸實(shí)現(xiàn)(二分查找)

折半查找法是一種查找方法,該方法通過(guò)不斷縮小一半查找的范圍揖庄,直到達(dá)到目的栗菜,所以效率比較高。

二分查找遞歸實(shí)現(xiàn)代碼:

/**
 * 遞歸實(shí)現(xiàn)二分查找
 */
int bin_search(int key[], int low, int high, int x){
    
    int mid;
    
    if (low > high)
        return -1;
    else{
        mid = (low + high)/2;
        
        if (key[mid] == x) return mid;
        
        if (x > key[mid]) {
            low = mid + 1;
            return bin_search(key, low, high, x); // 在序列的后半部分查找
        }else{
            high = mid - 1;
            return bin_search(key, low, high, x); //在序列的前半部分查找
        }
    }
}

測(cè)試:

int main(int argc, const char * argv[]) {
  
    int str[11] = {1,1,2,3,5,8,13,21,34,55,89};
    int n, addr;
    
    printf("請(qǐng)輸入待查找的關(guān)鍵字:");
    scanf("%d", &n);
    
    addr = bin_search(str, 0, 10, n);
    
    if (addr != -1) {
        printf("查找成功蹄梢!\n關(guān)鍵字%d所在位置是:%d\n", n, addr);
    }else{
        printf("查找失敻沓铩!\n");
    }
    return 0;
}
折半查找算法的遞歸實(shí)現(xiàn)

漢諾塔問(wèn)題

漢諾塔問(wèn)題起源

漢諾塔(又稱河內(nèi)塔)問(wèn)題是源于印度一個(gè)古老傳說(shuō)的益智玩具禁炒。大梵天創(chuàng)造世界的時(shí)候做了三根金剛石柱子而咆,在一根柱子上從下往上按照大小順序摞著64片黃金圓盤(pán)。大梵天命令婆羅門(mén)把圓盤(pán)從下面開(kāi)始按大小順序重新擺放在另一根柱子上幕袱。并且規(guī)定暴备,在小圓盤(pán)上不能放大圓盤(pán),在三根柱子之間一次只能移動(dòng)一個(gè)圓盤(pán)们豌。

漢諾塔問(wèn)題抽象成數(shù)學(xué)問(wèn)題

假設(shè)三個(gè)分別命名為X涯捻、Y、Z的塔座望迎,在塔座X上插有n個(gè)直徑大小各不相同障癌、依小到大編號(hào)為1,2,3...的圓盤(pán),現(xiàn)在要求將X軸上的n個(gè)圓盤(pán)移動(dòng)至Z上辩尊,并按照同樣順序疊排陪拘,圓盤(pán)移動(dòng)時(shí)必須循序一下規(guī)則:

  • 每次只能移動(dòng)一個(gè)圓盤(pán)常摧;
  • 圓盤(pán)可以插在X钠龙、Y口渔、Z中的任意一個(gè)塔座上;
  • 任何時(shí)刻都不能將一個(gè)較大的圓盤(pán)壓在較小的圓盤(pán)之上蒿涎。


用遞歸的思想來(lái)考慮漢諾塔問(wèn)題

漢諾塔問(wèn)題的實(shí)現(xiàn)步驟:

  • 先將前n-1(63)個(gè)盤(pán)子移動(dòng)到Y(jié)上哀托,確保大盤(pán)在小盤(pán)下;
  • 再將最底下的第n(64)個(gè)盤(pán)子移動(dòng)到Z上劳秋;
  • 最后將Y上的n-1(63)個(gè)盤(pán)子移動(dòng)到Z上仓手。

那么問(wèn)題就化解為解決一下兩個(gè)問(wèn)題:

  • 問(wèn)題一:將X上的n-1(63)個(gè)盤(pán)子借助Z移動(dòng)到Y(jié)上;
  • 問(wèn)題二:將Y上的n-1(63)個(gè)盤(pán)子借助X移動(dòng)到Z上玻淑。

解決這兩個(gè)步驟的思路相同:
問(wèn)題一:

  • 先將前n-2(62)個(gè)盤(pán)子移動(dòng)到Z上嗽冒,確保大盤(pán)在小盤(pán)下;
  • 再將最底下的第n-1(63)個(gè)盤(pán)子移動(dòng)到Y(jié)上补履;
  • 最后將Z上的n-2(62)個(gè)盤(pán)子移動(dòng)到Y(jié)上添坊。
    問(wèn)題二:
  • 先將前n-2(62)個(gè)盤(pán)子移動(dòng)到X上,確保大盤(pán)在小盤(pán)下箫锤;
  • 再將最底下的第n-1(63)個(gè)盤(pán)子移動(dòng)到Z上贬蛙;
  • 最后將Z上的n-2(62)個(gè)盤(pán)子移動(dòng)到Y(jié)上雨女。

得出相同的規(guī)律:這其實(shí)就是一個(gè)遞歸問(wèn)題。

代碼:

void hanoi(int n, char x, char y, char z){
    
    if (n == 1)  // 只有一層的情況
        printf("%c --> %c\n", x, z);
    else{
        hanoi(n - 1, x, z, y);          // 將 n-1 個(gè)盤(pán)子從 x 借助 z 移動(dòng)到 y 上
        printf("%c --> %c\n", x, z);     // 將第 n 個(gè)盤(pán)子從 x 移動(dòng)到 z 上
        hanoi(n-1, y, x, z);            // 將 n-1 個(gè)盤(pán)子從 y 借助 x 移動(dòng)到 z 上
    }
}

測(cè)試代碼:

int main(int argc, const char * argv[]) {

    int n;
    printf("請(qǐng)輸入漢諾塔的層數(shù):");
    scanf("%d", &n);
    printf("移動(dòng)的步驟如下:\n");
    
    hanoi(n, 'X', 'Y', 'Z');
    
    return 0;
}
漢諾塔遞歸算法

八皇后問(wèn)題遞歸解法

八皇后問(wèn)題是一個(gè)以國(guó)際象棋為背景的問(wèn)題:如何能夠在 8×8 的國(guó)際象棋棋盤(pán)上放置八個(gè)皇后阳准,使得任何一個(gè)皇后都無(wú)法直接吃掉其他的皇后氛堕?為了達(dá)到此目的,任兩個(gè)皇后都不能處于同一條橫行野蝇、縱行或斜線上讼稚。

用遞歸解決八皇后問(wèn)題的代碼

#include <stdio.h>

int count = 0;

/**
 * 判斷是否有危險(xiǎn)
 */
int notdanger(int row,int j,int (*chess)[8]){
    
    int i,k;
    
    //判斷列方向
    for(i=0;i<8;i++){
        if(*(*(chess+i)+j)==1) return 0; //這一列已存在皇后
    }
    
    //判斷左上方
    for(i=row,k=j;i>=0&&k>=0;i--,k--){
        if(*(*(chess+i)+k)==1) return 0; //左上方已存在皇后
    }
    
    //判斷右下方
    for(i=row,k=j;i<8&&k<8;i++,k++){
        if(*(*(chess+i)+k)==1) return 0; //右下方已存在皇后
    }
    
    //判斷左下方
    for(i=row,k=j;i<8&&k>=0;i++,k--){
        if(*(*(chess+i)+k)==1) return 0; //左下方已存在皇后
    }
    
    //判斷右上方
    for(i=row,k=j;i>=0&&k<8;i--,k++){
        if(*(*(chess+i)+k)==1) return 0; //右上方已存在皇后
    }
    
    return 1;
}

/**
 * 參數(shù)row:起始行
 * 參數(shù)n: 列數(shù)
 * 參數(shù)(*chess)[8]:指向棋盤(pán)每一行的指針
 */
void eightqueen(int row,int n,int (*chess)[8]){
    
    int chess2[8][8],i,j;  // 臨時(shí)棋盤(pán)
    
    for(i=0;i<8;i++){
        for(j=0;j<8;j++){
            chess2[i][j] = chess[i][j]; // 臨時(shí)棋盤(pán)賦值給棋盤(pán)
        }
    }
    
    if(row == 8){
        printf("第%d種:\n",count + 1);
        
        for(i=0;i<8;i++){
            for(j=0;j<8;j++){
                printf("%d ",*(*(chess2+i)+j));
            }
            printf("\n");
        }
        
        count ++;
        
    }else {
        //判斷這個(gè)位置是否有危險(xiǎn)
        //如果有危險(xiǎn),那繼續(xù)往下
        for(j=0;j<n;j++){
            if(notdanger(row,j,chess)){ //判斷是否危險(xiǎn)
                for(i=0;i<8;i++){ // 不危險(xiǎn)
                    *(*(chess2+row)+i)=0;
                }
                *(*(chess2+row)+j)=1;
                eightqueen(row+1,n,chess2);
            }
        }
    }
}

int main(int argc, const char * argv[]) {

    int chess[8][8];  // 8*8的棋盤(pán)
    int i,j;
    
    //初始化棋盤(pán)為0
    for(i=0;i<8;i++){
        for(j=0;j<8;j++){
            chess[i][j]=0;
        }
    }
    eightqueen(0,8,chess);//從第0行開(kāi)始依次以行為單位遍歷
    
    printf("\n總共有 %d 種解決辦法绕沈!\n\n",count);
    return 0;
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末锐想,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子七冲,更是在濱河造成了極大的恐慌痛倚,老刑警劉巖规婆,帶你破解...
    沈念sama閱讀 222,000評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件澜躺,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡抒蚜,警方通過(guò)查閱死者的電腦和手機(jī)掘鄙,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,745評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)嗡髓,“玉大人操漠,你說(shuō)我怎么就攤上這事《稣猓” “怎么了浊伙?”我有些...
    開(kāi)封第一講書(shū)人閱讀 168,561評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)长捧。 經(jīng)常有香客問(wèn)我嚣鄙,道長(zhǎng),這世上最難降的妖魔是什么串结? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,782評(píng)論 1 298
  • 正文 為了忘掉前任哑子,我火速辦了婚禮,結(jié)果婚禮上肌割,老公的妹妹穿的比我還像新娘卧蜓。我一直安慰自己,他們只是感情好把敞,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,798評(píng)論 6 397
  • 文/花漫 我一把揭開(kāi)白布弥奸。 她就那樣靜靜地躺著,像睡著了一般奋早。 火紅的嫁衣襯著肌膚如雪盛霎。 梳的紋絲不亂的頭發(fā)上冒冬,一...
    開(kāi)封第一講書(shū)人閱讀 52,394評(píng)論 1 310
  • 那天,我揣著相機(jī)與錄音摩渺,去河邊找鬼简烤。 笑死,一個(gè)胖子當(dāng)著我的面吹牛摇幻,可吹牛的內(nèi)容都是我干的横侦。 我是一名探鬼主播,決...
    沈念sama閱讀 40,952評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼绰姻,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼枉侧!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起狂芋,我...
    開(kāi)封第一講書(shū)人閱讀 39,852評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤榨馁,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后帜矾,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體翼虫,經(jīng)...
    沈念sama閱讀 46,409評(píng)論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,483評(píng)論 3 341
  • 正文 我和宋清朗相戀三年屡萤,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了珍剑。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,615評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡死陆,死狀恐怖招拙,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情措译,我是刑警寧澤别凤,帶...
    沈念sama閱讀 36,303評(píng)論 5 350
  • 正文 年R本政府宣布,位于F島的核電站领虹,受9級(jí)特大地震影響规哪,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜掠械,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,979評(píng)論 3 334
  • 文/蒙蒙 一由缆、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧猾蒂,春花似錦均唉、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,470評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至,卻和暖如春层扶,著一層夾襖步出監(jiān)牢的瞬間箫章,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,571評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工镜会, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留檬寂,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 49,041評(píng)論 3 377
  • 正文 我出身青樓戳表,卻偏偏與公主長(zhǎng)得像桶至,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子匾旭,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,630評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容

  • 前置文章:遞歸算法:www.reibang.com/p/703069f3ba3f . 漢諾塔問(wèn)題是來(lái)源于印度傳...
    郎小凱閱讀 770評(píng)論 0 1
  • http://www.liaoxuefeng.com/wiki/0014316089557264a6b348958...
    喵在野閱讀 465評(píng)論 0 4
  • 入群須知 1镣屹、先完整的瀏覽一遍群規(guī),了解群規(guī)有什么內(nèi)容价涝。 2女蜈、發(fā)出一個(gè)問(wèn)題之后,不要暫時(shí)的離開(kāi)電腦色瘩,如果沒(méi)有把握先...
    世上幾春秋閱讀 2,013評(píng)論 0 0
  • 雪伪窖,我再熟悉不過(guò)了! 想微微一笑泞遗,雖然不傾城惰许。因?yàn)橄氲窖┫玻业膬?nèi)心就有一種說(shuō)不出的美好感覺(jué)史辙,雖然它飄飛的日子里會(huì)伴...
    雪筆閱讀 461評(píng)論 0 2
  • 常見(jiàn)的路徑表達(dá)方式有四種 在這四種表達(dá)方式里面,前兩種是相對(duì)路徑佩伤,后兩種是絕對(duì)路徑聊倔。 相對(duì)路徑 相對(duì)路徑就是指相對(duì)...
    KelvinX閱讀 10,029評(píng)論 0 3