日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

递归算法深入分析

發(fā)布時間:2025/5/22 编程问答 22 豆豆
生活随笔 收集整理的這篇文章主要介紹了 递归算法深入分析 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

????轉(zhuǎn)載鏈接:http://www.cnblogs.com/zhangqqqf/archive/2008/09/12/1289730.html

?? ?C通過運(yùn)行時堆棧支持遞歸函數(shù)的實現(xiàn)。遞歸函數(shù)就是直接或間接調(diào)用自身的函數(shù)。 ???? 許多教科書都把計算機(jī)階乘和菲波那契數(shù)列用來說明遞歸,非常不幸我們可愛的著名的老潭老師的《C語言程序設(shè)計》一書中就是從階乘的計算開始的函數(shù)遞歸。導(dǎo)致讀過這本經(jīng)書的同學(xué)們,看到階乘計算第一個想法就是遞歸。但是在階乘的計算里,遞歸并沒有提供任何優(yōu)越之處。在菲波那契數(shù)列中,它的效率更是低的非??植馈?/span>

???? 這里有一個簡單的程序,可用于說明遞歸。程序的目的是把一個整數(shù)從二進(jìn)制形式轉(zhuǎn)換為可打印的字符形式。例如:給出一個值4267,我們需要依次產(chǎn)生字符‘4’,‘2’,‘6’,和‘7’。就如在printf函數(shù)中使用了%d格式碼,它就會執(zhí)行類似處理。

???? 我們采用的策略是把這個值反復(fù)除以10,并打印各個余數(shù)。例如,4267除10的余數(shù)是7,但是我們不能直接打印這個余數(shù)。我們需要打印的是機(jī)器字符集中表示數(shù)字‘7’的值。在ASCII碼中,字符‘7’的值是55,所以我們需要在余數(shù)上加上48來獲得正確的字符,但是,使用字符常量而不是整型常量可以提高程序的可移植性?!?’的ASCII碼是48,所以我們用余數(shù)加上‘0’,所以有下面的關(guān)系:

????????? ‘0’+ 0 =‘0’
???? ???? ‘0’+ 1 =‘1’
???? ???? ‘0’+ 2 =‘2’
?? ??     ?? ...

  從這些關(guān)系中,我們很容易看出在余數(shù)上加上‘0’就可以產(chǎn)生對應(yīng)字符的代碼。接著就打印出余數(shù)。下一步再取商的值,4267/10等于426。然后用這個值重復(fù)上述步驟。

  這種處理方法存在的唯一問題是它產(chǎn)生的數(shù)字次序正好相反,它們是逆向打印的。所以在我們的程序中使用遞歸來修正這個問題。

  我們這個程序中的函數(shù)是遞歸性質(zhì)的,因為它包含了一個對自身的調(diào)用。乍一看,函數(shù)似乎永遠(yuǎn)不會終止。當(dāng)函數(shù)調(diào)用時,它將調(diào)用自身,第2次調(diào)用還將調(diào)用自身,以此類推,似乎永遠(yuǎn)調(diào)用下去。這也是我們在剛接觸遞歸時最想不明白的事情。但是,事實上并不會出現(xiàn)這種情況。

  這個程序的遞歸實現(xiàn)了某種類型的螺旋狀while循環(huán)。while循環(huán)在循環(huán)體每次執(zhí)行時必須取得某種進(jìn)展,逐步迫近循環(huán)終止條件。遞歸函數(shù)也是如此,它在每次遞歸調(diào)用后必須越來越接近某種限制條件。當(dāng)遞歸函數(shù)符合這個限制條件時,它便不在調(diào)用自身。

在程序中,遞歸函數(shù)的限制條件就是變量quotient為零。在每次遞歸調(diào)用之前,我們都把quotient除以10,所以每遞歸調(diào)用一次,它的值就越來越接近零。當(dāng)它最終變成零時,遞歸便告終止。

/*接受一個整型值(無符號0,把它轉(zhuǎn)換為字符并打印它,前導(dǎo)零被刪除*/

#include <stdio.h>
int binary_to_ascii( unsigned int value) { ???? ?????unsigned int quotient; ?? ? ??   quotient = value / 10; ??   if( quotient != 0) ?? ???     binary_to_ascii( quotient); ??   putchar ( value % 10 + '0' ); }

遞歸是如何幫助我們以正確的順序打印這些字符呢?下面是這個函數(shù)的工作流程。
?????? 1. 將參數(shù)值除以10
?????? 2. 如果quotient的值為非零,調(diào)用binary-to-ascii打印quotient當(dāng)前值的各位數(shù)字

  3. 接著,打印步驟1中除法運(yùn)算的余數(shù)

  注意在第2個步驟中,我們需要打印的是quotient當(dāng)前值的各位數(shù)字。我們所面臨的問題和最初的問題完全相同,只是變量quotient的值變小了。我們用剛剛編寫的函數(shù)(把整數(shù)轉(zhuǎn)換為各個數(shù)字字符并打印出來)來解決這個問題。由于quotient的值越來越小,所以遞歸最終會終止。

  一旦你理解了遞歸,閱讀遞歸函數(shù)最容易的方法不是糾纏于它的執(zhí)行過程,而是相信遞歸函數(shù)會順利完成它的任務(wù)。如果你的每個步驟正確無誤,你的限制條件設(shè)置正確,并且每次調(diào)用之后更接近限制條件,遞歸函數(shù)總是能正確的完成任務(wù)。

  但是,為了理解遞歸的工作原理,你需要追蹤遞歸調(diào)用的執(zhí)行過程,所以讓我們來進(jìn)行這項工作。追蹤一個遞歸函數(shù)的執(zhí)行過程的關(guān)鍵是理解函數(shù)中所聲明的變量是如何存儲的。當(dāng)函數(shù)被調(diào)用時,它的變量的空間是創(chuàng)建于運(yùn)行時堆棧上的。以前調(diào)用的函數(shù)的變量扔保留在堆棧上,但他們被新函數(shù)的變量所掩蓋,因此是不能被訪問的。

  當(dāng)遞歸函數(shù)調(diào)用自身時,情況于是如此。每進(jìn)行一次新的調(diào)用,都將創(chuàng)建一批變量,他們將掩蓋遞歸函數(shù)前一次調(diào)用所創(chuàng)建的變量。當(dāng)我追蹤一個遞歸函數(shù)的執(zhí)行過程時,必須把分?jǐn)?shù)不同次調(diào)用的變量區(qū)分開來,以避免混淆。

  程序中的函數(shù)有兩個變量:參數(shù)value和局部變量quotient。下面的一些圖顯示了堆棧的狀態(tài),當(dāng)前可以訪問的變量位于棧頂。所有其他調(diào)用的變量飾以灰色的陰影,表示他們不能被當(dāng)前正在執(zhí)行的函數(shù)訪問。

假定我們以4267這個值調(diào)用遞歸函數(shù)。當(dāng)函數(shù)剛開始執(zhí)行時,堆棧的內(nèi)容如下圖所示:?
?


執(zhí)行除法之后,堆棧的內(nèi)容如下:


??
接著,if語句判斷出quotient的值非零,所以對該函數(shù)執(zhí)行遞歸調(diào)用。當(dāng)這個函數(shù)第二次被調(diào)用之初,堆棧的內(nèi)容如下:
?


堆棧上創(chuàng)建了一批新的變量,隱藏了前面的那批變量,除非當(dāng)前這次遞歸調(diào)用返回,否則他們是不能被訪問的。再次執(zhí)行除法運(yùn)算之后,堆棧的內(nèi)容如下:
?


quotient的值現(xiàn)在為42,仍然非零,所以需要繼續(xù)執(zhí)行遞歸調(diào)用,并再創(chuàng)建一批變量。在執(zhí)行完這次調(diào)用的出發(fā)運(yùn)算之后,堆棧的內(nèi)容如下:
?


此時,quotient的值還是非零,仍然需要執(zhí)行遞歸調(diào)用。在執(zhí)行除法運(yùn)算之后,堆棧的內(nèi)容如下:
?


  不算遞歸調(diào)用語句本身,到目前為止所執(zhí)行的語句只是除法運(yùn)算以及對quotient的值進(jìn)行測試。由于遞歸調(diào)用這些語句重復(fù)執(zhí)行,所以它的效果類似循環(huán):當(dāng)quotient的值非零時,把它的值作為初始值重新開始循環(huán)。但是,遞歸調(diào)用將會保存一些信息(這點與循環(huán)不同),也就好是保存在堆棧中的變量值。這些信息很快就會變得非常重要。

  現(xiàn)在quotient的值變成了零,遞歸函數(shù)便不再調(diào)用自身,而是開始打印輸出。然后函數(shù)返回,并開始銷毀堆棧上的變量值。

每次調(diào)用putchar得到變量value的最后一個數(shù)字,方法是對value進(jìn)行模10取余運(yùn)算,其結(jié)果是一個0到9之間的整數(shù)。把它與字符常量‘0’相加,其結(jié)果便是對應(yīng)于這個數(shù)字的ASCII字符,然后把這個字符打印出來。?

???輸出4:

?


接著函數(shù)返回,它的變量從堆棧中銷毀。接著,遞歸函數(shù)的前一次調(diào)用重新繼續(xù)執(zhí)行,她所使用的是自己的變量,他們現(xiàn)在位于堆棧的頂部。因為它的value值是42,所以調(diào)用putchar后打印出來的數(shù)字是2。

??輸出42:

?


接著遞歸函數(shù)的這次調(diào)用也返回,它的變量也被銷毀,此時位于堆棧頂部的是遞歸函數(shù)再前一次調(diào)用的變量。遞歸調(diào)用從這個位置繼續(xù)執(zhí)行,這次打印的數(shù)字是6。在這次調(diào)用返回之前,堆棧的內(nèi)容如下:

? 輸出426:

?


現(xiàn)在我們已經(jīng)展開了整個遞歸過程,并回到該函數(shù)最初的調(diào)用。這次調(diào)用打印出數(shù)字7,也就是它的value參數(shù)除10的余數(shù)。

? 輸出4267:

?


然后,這個遞歸函數(shù)就徹底返回到其他函數(shù)調(diào)用它的地點。
如果你把打印出來的字符一個接一個排在一起,出現(xiàn)在打印機(jī)或屏幕上,你將看到正確的值:4267

漢諾塔問題遞歸算法分析:

  一個廟里有三個柱子,第一個有64個盤子,從上往下盤子越來越大。要求廟里的老和尚把這64個盤子全部移動到第三個柱子上。移動的時候始終只能小盤子壓著大盤子。而且每次只能移動一個。

  1、此時老和尚(后面我們叫他第一個和尚)覺得很難,所以他想:要是有一個人能把前63個盤子先移動到第二個柱子上,我再把最后一個盤子直接移動到第三個柱子,再讓那個人把剛才的前63個盤子從第二個柱子上移動到第三個柱子上,我的任務(wù)就完成了,簡單。所以他找了比他年輕的和尚(后面我們叫他第二個和尚),命令:

????????? ① 你丫把前63個盤子移動到第二柱子上

???? ???? ② 然后我自己把第64個盤子移動到第三個柱子上后?

????????? ③ 你把前63個盤子移動到第三柱子上?

????? 2、第二個和尚接了任務(wù),也覺得很難,所以他也和第一個和尚一樣想:要是有一個人能把前62個盤子先移動到第三個柱子上,我再把最后一個盤子直接移動到第二個柱子,再讓那個人把剛才的前62個盤子從第三個柱子上移動到第三個柱子上,我的任務(wù)就完成了,簡單。所以他也找了比他年輕的和尚(后面我們叫他第三和尚),命令:?

????????? ① 你把前62個盤子移動到第三柱子上?

???? ???? ② 然后我自己把第63個盤子移動到第二個柱子上后?

???? ???? ③ 你把前62個盤子移動到第二柱子上?

  3、第三個和尚接了任務(wù),又把移動前61個盤子的任務(wù)依葫蘆話瓢的交給了第四個和尚,等等遞推下去,直到把任務(wù)交給了第64個和尚為止(估計第64個和尚很郁悶,沒機(jī)會也命令下別人,因為到他這里盤子已經(jīng)只有一個了)。

  4、到此任務(wù)下交完成,到各司其職完成的時候了。完成回推了:

第64個和尚移動第1個盤子,把它移開,然后第63個和尚移動他給自己分配的第2個盤子。
第64個和尚再把第1個盤子移動到第2個盤子上。到這里第64個和尚的任務(wù)完成,第63個和尚完成了第62個和尚交給他的任務(wù)的第一步。?

  從上面可以看出,只有第64個和尚的任務(wù)完成了,第63個和尚的任務(wù)才能完成,只有第2個和尚----第64個和尚的任務(wù)完成后,第1個和尚的任務(wù)才能完成。這是一個典型的遞歸問題。 現(xiàn)在我們以有3個盤子來分析:

第1個和尚命令:

???? ???? ① 第2個和尚你先把第一柱子前2個盤子移動到第二柱子。(借助第三個柱子)

???? ???? ② 第1個和尚我自己把第一柱子最后的盤子移動到第三柱子。

???? ???? ③ 第2個和尚你把前2個盤子從第二柱子移動到第三柱子。?

   很顯然,第二步很容易實現(xiàn)(哎,人總是自私地,把簡單留給自己,困難的給別人)。

其中第一步,第2個和尚他有2個盤子,他就命令:

???? ???? ① 第3個和尚你把第一柱子第1個盤子移動到第三柱子。(借助第二柱子)?

???? ???? ② 第2個和尚我自己把第一柱子第2個盤子移動到第二柱子上。?

????????? ③ 第3個和尚你把第1個盤子從第三柱子移動到第二柱子。

   同樣,第二步很容易實現(xiàn),但第3個和尚他只需要移動1個盤子,所以他也不用在下派任務(wù)了。(注意:這就是停止遞歸的條件,也叫邊界值)

第三步可以分解為,第2個和尚還是有2個盤子,命令:?

????????? ① 第3個和尚你把第二柱子上的第1個盤子移動到第一柱子。

???? ???? ② 第2個和尚我把第2個盤子從第二柱子移動到第三柱子。

???? ???? ③ 第3個和尚你把第一柱子上的盤子移動到第三柱子。?
????????????????? ?
分析組合起來就是:1→3 1→2 3→2?借助第三個柱子移動到第二個柱子 |1→3?自私人留給自己的活|?2→1 2→3 1→3借助第一個柱子移動到第三個柱子|共需要七步。

如果是4個盤子,則第一個和尚的命令中第1步和第3步各有3個盤子,所以各需要7步,共14步,再加上第1個和尚的1步,所以4個盤子總共需要移動7+1+7=15步,同樣,5個盤子需要15+1+15=31步,6個盤子需要31+1+31=64步……由此可以知道,移動n個盤子需要(2的n次方)-1步。

   從上面整體綜合分析可知把n個盤子從1座(相當(dāng)?shù)谝恢?#xff09;移到3座(相當(dāng)?shù)谌?#xff09;:

(1)把1座上(n-1)個盤子借助3座移到2座。?
?????(2)把1座上第n個盤子移動3座。?
(3)把2座上(n-1)個盤子借助1座移動3座。?

下面用hanoi(n,a,b,c)表示把1座n個盤子借助2座移動到3座。?

很明顯:??? (1)步上是 hanoi(n-1,1,3,2)?
???? ????????? (3)步上是 hanoi(n-1,2,1,3)?
用C語言表示出來,就是:
#include <stdio.h> int method(int n,char a, char b) { ?????printf("number..%d..form..%c..to..%c.."n",n,a,b); ?????return 0; } int hanoi(int n,char a,char b,char c) { ?????if( n==1 ) move (1,a,c); ?????else ???? ?????{ ???? ??????????hanoi(n-1,a,c,b); ????????? ?????move(n,a,c); ???? ??????????hanoi(n-1,b,a,c); ???? ?????}; ?????return 0; } int main() { ?????int num; ?????scanf("%d",&num); ?????hanoi(num,'A','B','C'); ?????return 0;

轉(zhuǎn)載于:https://www.cnblogs.com/shishidemeitian/p/4139254.html

《新程序員》:云原生和全面數(shù)字化實踐50位技術(shù)專家共同創(chuàng)作,文字、視頻、音頻交互閱讀

總結(jié)

以上是生活随笔為你收集整理的递归算法深入分析的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 亚洲天堂一区二区三区四区 | 久久久久久99精品 | 亚洲精品一二三四区 | 久久精品69| 欧美性大战xxxxx久久久 | 欧美福利视频在线 | 国产伦人伦偷精品视频 | 一区二区三区视频免费观看 | 少妇人妻好深好紧精品无码 | 麻豆91茄子在线观看 | 伊人影院综合在线 | 精品乱子伦 | 亚洲自拍偷拍第一页 | 搡老熟女国产 | 那里有毛片看 | 成年人视频免费看 | 国产成人激情视频 | 人成网站在线观看 | 日韩大片免费看 | 可以在线观看av的网站 | 国产一级视频在线观看 | av天天在线 | 亚洲视频二区 | 日韩一级色 | 不卡视频国产 | 激情区| 日本不卡一区二区三区视频 | 亚洲国产日韩欧美 | 国产一区二区在线视频观看 | 天堂少妇| 天堂精品一区二区三区 | 国产精品网站免费 | 91丨porny丨| 欧美黄视频在线观看 | 久久婷婷综合色丁香五月 | 久久国产露脸精品国产 | 欧美日韩精品在线观看 | 88av网| 国产黄色小视频在线观看 | 黄色动漫免费在线观看 | 亚洲av无码一区二区三区在线播放 | 3p在线播放| 欧美福利在线观看 | 精品人妻码一区二区三区红楼视频 | 国产日韩欧美一区二区 | 91精品久久久久久久久久 | 97超级碰碰| xxx性欧美| 精品少妇一区二区三区 | 亚洲成人一 | 精品久久久久久久久久久久 | 日日夜夜狠狠爱 | 亚洲综合五月 | av特黄| 水果派解说av | 亚洲色图88 | 精品国产av鲁一鲁一区 | 97国产在线观看 | 色屁屁www影院免费观看入口 | 在线中文字幕一区二区 | 国产亚洲精久久久久久无码苍井空 | 九热精品视频 | 人人爱人人插 | 91深夜视频 | 成人黄色国产 | 欧美一区二区三区爽爽爽 | 国产精品三级久久久久久电影 | av大西瓜| 黄网在线看 | 美女av影院 | 欧美福利第一页 | av中文在线资源 | 国产成人精品一区在线播放 | 超碰97在线资源站 | 欧美日本在线视频 | 按摩毛片| 国产xxxxx在线观看 | 超碰在97 | 色呦呦国产精品 | 人人澡人人澡人人澡 | av黄色免费观看 | 精品久久在线 | 五月天在线播放 | 开心激情久久 | 中文一二三区 | 一女三黑人理论片在线 | 99久久精品国产成人一区二区 | 日本打白嫩屁股视频 | 色综合加勒比 | 狠狠躁日日躁夜夜躁av | 久久偷看各类女兵18女厕嘘嘘 | 日本少妇高潮喷水xxxxxxx | 特大黑人巨交吊性xx | 黄色大片黄色大片 | 日韩精品一卡 | 日本一区二区三区在线播放 | 中文字幕在线导航 | 欧美黑人啪啪 | 日韩高清av |