函數(shù)的遞歸調(diào)用與分治策略_第1頁
函數(shù)的遞歸調(diào)用與分治策略_第2頁
函數(shù)的遞歸調(diào)用與分治策略_第3頁
函數(shù)的遞歸調(diào)用與分治策略_第4頁
函數(shù)的遞歸調(diào)用與分治策略_第5頁
已閱讀5頁,還剩10頁未讀 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)

文檔簡介

1、函數(shù)的遞遞歸調(diào)用用與分治治策略遞歸方法法是算法法和程序序設(shè)計中中的一種種重要技技術(shù)。遞遞歸方法法即通過過函數(shù)或或過程調(diào)調(diào)用自身身將問題題轉(zhuǎn)化為為本質(zhì)相相同但規(guī)規(guī)模較小小的子問問題。遞遞歸方法法具有易易于描述述和理解解、證明明簡單等等優(yōu)點,在動態(tài)態(tài)規(guī)劃、貪心算算法、回回溯法等等諸多算算法中都都有著極極為廣泛泛的應(yīng)用用,是許許多復(fù)雜雜算法的的基礎(chǔ)。遞歸方方法中所所使用的的“分而治治之”的策略略也稱分分治策略略。遞歸方法法的構(gòu)造造構(gòu)造遞歸歸方法的的關(guān)鍵在在于建立立遞歸關(guān)關(guān)系。這這里的遞遞歸關(guān)系系可以是是遞歸描描述的,也可以以是遞推推描述的的。下面面由一個個求n的的階乘的的程序為為例,總總結(jié)出構(gòu)構(gòu)造遞

2、歸歸方法的的一般步步驟。例1從鍵盤盤輸入正正整數(shù)NN(0=N=1時時,N!=N*(N-1)!(N=1時,0!=1),這就是是一種遞遞歸關(guān)系系。對于于特定的的K!,它只與與K與(K-11)!有有關(guān)。步驟22確定定遞歸邊邊界 在在步驟11的遞歸歸關(guān)系中中,對大大于k的的Un的的求解將將最終歸歸結(jié)為對對Uk的的求解。這里的的Uk稱稱為遞歸歸邊界(或遞歸歸出口)。在本本例中,遞歸邊邊界為kk=0,即0!=1。對于任任意給定定的N!,程序序?qū)⒆罱K終求解到到0!。確定遞歸歸邊界十十分重要要,如果果沒有確確定遞歸歸邊界,將導(dǎo)致致程序無無限遞歸歸而引起起死循環(huán)環(huán)。例如如以下程程序:#inccludde int

3、 f(iint x) reeturrn(ff(x-1);mainn() coout=1時n!= 11 當當N=00時再將這種種關(guān)系翻翻譯為代代碼,即即一個函函數(shù):longg f(intt n) if (n=0) rretuurn(1); elsse rretuurn(n*ff(n-1);步驟44完善善程序 主要的的遞歸函函數(shù)已經(jīng)經(jīng)完成,將程序序依題意意補充完完整即可可。/exx1.ccpp#inccludde longg f(intt n) if (n=0) rretuurn(1); elsse rretuurn(n*ff(n-1);mainn() intt n; cinnnn; couute

4、nddl=33)。從從鍵盤輸輸入N,輸出AA(N)。分析遞歸關(guān)關(guān)系十分分明顯,由A(N)的的表達式式給出。需要注注意的是是本例中中對于NN=33,A(N)的的值與AA(N-1)和和A(NN-2)都有關(guān)關(guān)。代碼/exx2.ccpp#inccludde longg fiibonnaccci(iint x) if ( (x=1) | (x=2) ) rretuurn(1); elsse rretuurn(fibbonaaccii(x-1)+fibbonaaccii(x-2);mainn() intt n; cinnnn; couutenddlfibbonaaccii(n); 例33Haanoii塔問

5、題題。 問題題描述在霍比比特人的的圣廟里里,有一一塊黃銅銅板,上上面插著著3根寶寶石針(分別為為A號,B號和和C號)。在AA號針上上從下到到上套著著從大到到小的nn個圓形形金片。現(xiàn)要將將A針上上的金片片全部移移到C針針上,且且仍按照照原來的的順序疊疊置。移移動的規(guī)規(guī)則如下下:這些些金片只只能在33根針間間移動,一次只只能一片片,且任任何時候候都不允允許將較較大的金金片壓在在較小的的上面。從鍵盤盤輸入nn,要求求給出移移動的次次數(shù)和方方案。分析由金片片的個數(shù)數(shù)建立遞遞歸關(guān)系系。當nn=1時時,只要要將唯一一的金片片從A移移到C即即可。當當n11時,只只要把較較小的(n-11)片按按移動規(guī)規(guī)則從A

6、A移到BB,再將將剩下的的最大的的從A移移到C(即中間間“借助”B把金金片從AA移到CC),再再將B上上的(nn-1)個金片片按照規(guī)規(guī)則從BB移到CC(中間間“借助”A)。本題的特特點在于于不容易易用數(shù)學(xué)學(xué)語言寫寫出具體體的遞歸歸函數(shù),但遞歸歸關(guān)系明明顯,仍仍可用遞遞歸方法法求解。代碼/exx3.ccpp#inccludde hanooi(iint n,ccharr t11,chhar t2,chaar tt3) if (n=1) ccoutt1 tt1 tt3enddl; elsse haanoii(n-1,tt1,tt3,tt2); cooutn t1 t3enndl; haanoii(n

7、-1,tt2,tt1,tt3); mainn() intt n; couutnn; couutAnnsweer:eendll; hannoi(n,A,B,CC);函數(shù)遞歸歸調(diào)用的的應(yīng)用與與分治策策略許多算法法都采用用了分治治策略求求解,而而可以說說分治與與遞歸是是一對孿孿生兄弟弟,它們們經(jīng)常同同時被應(yīng)應(yīng)用于算算法的設(shè)設(shè)計中。下面討討論著名名的Caatallan數(shù)數(shù)問題,人們在在對它的的研究中中充分應(yīng)應(yīng)用了分分治策略略。例4Cattalaan數(shù)問問題。問題描描述一一個凸多多邊形,通過不不相交于于n邊形形內(nèi)部的的對角線線,剖分分為若干干個三角角形。求求不同的的剖分方方案總數(shù)數(shù)H(nn)。HH(n)

8、即為CCataalann數(shù)。例例如,nn=5時時H(55)=55。分析Cattalaan數(shù)問問題有著著明顯的的遞歸子子問題特特征。在在計算CCataalann數(shù)時雖雖然可以以推導(dǎo)出出只關(guān)于于n的一一般公式式,但在在推導(dǎo)過過程中卻卻要用到到遞歸公公式。下下面討論論三種不不同的解解法,其其中第三三種解法法沒有使使用遞歸歸,它是是由前兩兩種解法法推導(dǎo)而而出的。解法11對于于多邊形形V1VV2Vn,對角線線V1VVi(ii=3,4,n-1)將將其分為為兩部分分,一部部分是ii邊形,另一部部分是nn-i+1邊形形。因此此,以對對角線VV1Vii為一個個剖分方方案的剖剖分方案案數(shù)為HH(i)*H(n-ii

9、+1)。還有有一種的的特殊情情形,是是對角線線V2VVn將其其分為一一個三角角形V11V2VVn和一一個n-2+11邊形。為了讓讓它同樣樣符合粗粗體字給給出的公公式,規(guī)規(guī)定H(2)=1。于于是得到到公式:H(n)=H(ii)*HH(n-i+11) (i=22,3,n-1) -公式式(1)H(2)=1有了這個個遞歸關(guān)關(guān)系式,就可以以用遞推推法或遞遞歸法解解出H(n)。解法22從VV1向除除了V22和Vnn外的nn-3個個頂點可可作n-3條對對角線。每一條條對角線線V1VVi把多多邊形剖剖分成兩兩部分,剖分方方案數(shù)為為H(ii)*HH(n-i+22),由由于Vii可以是是V3VV4Vn-1中的的任

10、一點點,且VV1可換換成V22,V33,Vnn中任一一點也有有同樣的的結(jié)果??紤]到到同一條條對角線線在2個個頂點被被重復(fù)計計算了一一次,于于是對每每個由頂頂點和對對角線確確定的剖剖分方案案都乘以以1/22,故有有H(n)=n(1/2)HH(i)*H(n-ii+2) (ii=3,4,n-1)把(1/2)提提到外面,H(n)=n/(2*(n-3)H(ii)*HH(n-i+22) (i=33,4,n-1) -公式式(2)規(guī)定H(2)=H(33)=11,這是是合理的的。由公式(2)和和H(22)=11,同樣樣可以用用遞推法法或遞歸歸法解出出H(nn)。解法33 把把公式(1)中中的自變變量改為為n+1

11、1,再將將剛剛得得出的公公式(22)代入入公式(1),得到H(n+1)=H(ii)*HH(n-i+22) (i=22,3,n) 由公式式(1)H(n+1)=2*HH(n)+H(ii)*HH(n-i+22) (i=33,4,n-1) 由由H(22)=11H(n+1)=(4nn-6)/n*H(nn) 由公公式(22)H(n)=(44n-110)/(n-1)*H(nn-1) -公公式(33)這是一個個較之前前兩種解解法更為為簡單的的遞歸公公式,還還可以繼繼續(xù)簡化化為H(n)=1/(n-1)*C(nn-2,2n-4) -公式式(4)這就不需需要再使使用遞歸歸算法了了。然而而在程序序設(shè)計上上,公式式(4

12、)反而顯顯得更加加復(fù)雜,因為要要計算階階乘。因因此最后后給出由由公式(3)作作為理論論依據(jù)范范例程序序代碼。代碼相相當簡單單,這都都歸功于于剛才的的推導(dǎo)。如果用用前兩種種解法中中的遞歸歸關(guān)系,程序會會變得復(fù)復(fù)雜且容容易寫錯錯。因此此,有時時對具體體問題將將遞歸關(guān)關(guān)系公式式進行必必要的化化簡也是是至關(guān)重重要的。代碼/exx4.ccpp#inccludde #deffinee MAAXN 1000longg f(intt x) iff (xx=33) retturnn(1); ellse retturnn(44*x-10)*f(x-11)/(x-11);mainn() innt nn; coout

13、n; iff ( (n=33) ) couutThhe aanswwer is:f(nn);本例編程程時還有有一個細細節(jié)問題題需要注注意。注注意函數(shù)數(shù)f中的的斜體部部分,按按照公式式(4)計算時時一定要要先進行行乘法再再進行除除法運算算,因為為(4*x-110)并并不總能能整除(x-11),如如果先進進行除法法則除出出的小數(shù)數(shù)部分將將自動被被舍去,從而導(dǎo)導(dǎo)致得到到不正確確的解。數(shù)學(xué)上許許多有重重要意義義的計數(shù)數(shù)問題都都可以歸歸結(jié)為對對Cattalaan數(shù)的的研究??梢钥纯吹剑颈纠械牡倪f歸關(guān)關(guān)系經(jīng)簡簡化還是是相當簡簡單的。下面討討論一個個遞歸關(guān)關(guān)系略為為復(fù)雜的的例子。例5快速排排序問題題???/p>

14、速排序序是程序序設(shè)計中中經(jīng)常涉涉及的一一種排序序算法。它的最最好時間間復(fù)雜度度為O(nloog2nn),最最差為OO(n22),是是一種不不穩(wěn)定的的排序方方法(大大小相同同的數(shù)在在排序后后可能交交換位置置)。算法描描述快快速排序序的一種種基本思思想是:要將nn個數(shù)按按由小到到大排列列,在待待排序的的n個數(shù)數(shù)中選取取任一個個數(shù)(在在本例中中取第一一個),稱為基基準數(shù),在每一一次快速速排序過過程中設(shè)設(shè)置兩個個指示器器i和jj,對基基準數(shù)左左邊和右右邊的數(shù)數(shù)同時從從最左(i)和和最右(j)開開始進行行掃描(i逐11遞增,j逐11遞減),直到到找到從從左邊開開始的某某個i大大于或等等于基準準數(shù),從從右

15、邊開開始的某某個j小小于或等等于基準準數(shù)。一一旦發(fā)現(xiàn)現(xiàn)這樣的的i和jj(暫且且稱之為為一個“逆序?qū)Α保瑒t則把第ii個數(shù)和和第j個個數(shù)交換換位置,這樣它它們就不不再是逆逆序?qū)α肆耍o接接著再將將i遞增增1,jj遞減11。如此此反復(fù),在交換換過有限限個逆序序?qū)?,i和jj將越來來越靠近近,最后后“相遇”,即ii和j指指向同一一個數(shù),暫且稱稱之為相相遇數(shù)(極端情情況下,如果一一開始就就不存在在逆序?qū)?,i和和j將直直接“相遇”)。相相遇后就就保證數(shù)數(shù)列中沒沒有逆序序?qū)α耍ǔ嗽谠谏鲜龅牡臉O端情情況下基基準數(shù)和和自身也也算構(gòu)成成一個逆逆序?qū)?,注意粗粗體字給給出的逆逆序?qū)Φ牡亩x)。繼續(xù)續(xù)掃描,非極

16、端端情況下下,由于于數(shù)列中中已經(jīng)沒沒有逆序序?qū)Γ琲i遞增11(如果果相遇數(shù)數(shù)小于基基準數(shù))或者jj遞減11(如果果相遇數(shù)數(shù)大于基基準數(shù))后即算算完成了了一趟快快速排序序,這時時第1到到第j個個數(shù)中的的每個都都保證小小于或等等于基準準數(shù),第第i到第第n個數(shù)數(shù)中的每每個保證證大于或或等于基基準數(shù)。此時,遞歸調(diào)調(diào)用函數(shù)數(shù),對第第1到第第j個數(shù)數(shù)和第ii到第nn個數(shù)分分別再進進行一趟趟快速排排序。如如果在極極端情況況下,程程序認為為基準數(shù)數(shù)和自身身構(gòu)成逆逆序?qū)?,則將基基準數(shù)與與自身交交換(這這其實沒沒有作用用)之后后i遞增增1,jj遞減11(注意意斜體字字給出的的對逆序序?qū)Φ奶幪幚矸椒ǚǎ?,同同樣對?/p>

17、第1到第第j個數(shù)數(shù)和第ii到第nn個數(shù)分分別再進進行一趟趟快速排排序。最后的問問題就是是確定遞遞歸邊界界。由于于被排序序的數(shù)列列將不斷斷被劃分分為兩個個至少含含一個數(shù)數(shù)的子列列(因為為在每趟趟排序最最后進行行遞歸調(diào)調(diào)用函數(shù)數(shù)時ij),最后后子列的的長度將將變?yōu)?1。這就就是遞歸歸的邊界界。在程程序?qū)崿F(xiàn)現(xiàn)是,本本著“能排則則排”的原則則,只要要第一個個數(shù)小于于j(或或者第ii個數(shù)小小于最后后一個數(shù)數(shù)),即即進行遞遞歸。主程序序(遞歸歸函數(shù)體體)voidd QuuickkSorrt(RRecTTypee R ,intt s,intt t) innt ii=s,j=tt,k; ReecTyype t

18、emmp; iff (ssii&RRj.keeyttempp.keey) j-; iif(iij) RRi=Rj; ii+; whhilee( iij&Ri.keyyteemp.keyy) i+; iif(iij) RRj=Ri; jj-; RRi=teemp; QQuicckSoort(R,ss,i-1); QQuicckSoort(R,ii+1,t); 例66“九宮陣陣”智力游游戲。問題描描述一一個99方陣陣,由99個“九宮格格”組成,每個九九宮格又又由33共99個小格格子組成成。請在在每個空空白小格格子里面面填上119的的數(shù)字,使每個個數(shù)字在在每個九九宮格內(nèi)內(nèi)以及在在整個九九宮陣中中的每

19、行行、每列列上均出出現(xiàn)一次次。(1)編編程將下下面圖中中的九宮宮陣補充充完整。(2)討討論是否否可能給給出“九宮陣陣”的全部部解?分析本題可可利用回回溯法解解決,其其基本思思想為深深度優(yōu)先先搜索(DFSS),這這也是一一種以分分治策略略為基礎(chǔ)礎(chǔ)的算法法?;厮菟莘ㄅc純純粹的DDFS不不同的是是,它在在搜索過過程中不不斷殺死死不合題題意的結(jié)結(jié)點。這這一點保保證了解解法的效效率。首先考慮慮如何得得出全部部解的情情況。解空間樹樹容易構(gòu)構(gòu)造,只只需按順順序(從從第一行行第一個個數(shù)字開開始到第第一行最最后一個個,然后后第二行行,一一直到最最后一行行最后一一個數(shù)字字)“嘗試”填入數(shù)數(shù)字即可可。為了解決決這個

20、問問題,我我們需要要先編寫寫一個函函數(shù)chheckk,其原原型為iint cheeck(intt i,intt j,intt k),用于于求第ii行第jj列能否否填上數(shù)數(shù)字k。如果可可以,返返回1,否則返返回0。由于我我們是按按順序填填入數(shù)字字的,看看起來一一個數(shù)字字后面的的數(shù)字并并不在判判斷能否否填的范范圍內(nèi)。但為了了解決題題中某個個特解問問題的方方便,還還是引入入較為嚴嚴謹?shù)呐信袛喾椒ǚ?。函?shù)chheckk代碼如如下:int cheeck(intt i,intt j,intt k) innt ll,m,pi,pj; /1. Cheeck thee liine foor (l=11;l=9;

21、l+) if ( (l!=j) & (ail!=0) & (aail=kk) ) rretuurn(0); /2. Cheeck thee coolummn foor (l=11;l=9;l+) if ( (l!=i) & (alj!=0) & (aalj=kk) ) rretuurn(0); /3. Cheeck thee 3xx3 mmatrrix /3.11 Fiirsttly wee wiill havve tto cchecck tthe parrentt_i(pi) annd ppareent_j(ppj) iff (ii=33) ppi=11; ellse if (i=6) pi

22、i=4; ellse pi=7; iff (jj=33) ppj=11; ellse if (j=6) pjj=4; ellse pj=7; /3.22 Noow wwe ccan cheeck it foor (l=00;l=2;l+) ffor (m=0;mm=22;m+) iff ( (ppi+ll)!=i) & (ppj+mm)!=j) ) if ( ( api+lpj+m!=0 ) & ( api+lpj+m=k ) ) reeturrn(00); reeturrn(11);結(jié)合注釋釋很容易易就能接接受函數(shù)數(shù)的思想想,不予予過多說說明。下面考慮慮程序最最重要的的部分,即遞歸歸函數(shù)。思

23、路是是這樣的的:假設(shè)設(shè)某一格格能填入入某數(shù),把這個個格子看看成解空空間樹的的一個結(jié)結(jié)點,由由它可以以擴展出出9個兒兒子,即即下一格格填什么么數(shù)(由由1到99逐個嘗嘗試)。對下一一格,同同樣這樣樣考慮。不斷用用函數(shù)cchecck函數(shù)數(shù)考察某某一個能能否填入入某數(shù),一旦函函數(shù)chheckk返回00,則殺殺死這個個結(jié)點。如果能一一直填到到最后一一個數(shù),結(jié)點仍仍未被殺殺死,則則這是一一個解。這種思想想可用偽偽代碼表表示如下下:procceduure baccktrrackk(i,j,kk:inntegger); iff chheckk(i,j,kk)=ttruee thhen beeginn aai,

24、j=k; GGeneeratte_nnextt_i_andd_j; iif ii100 thhen bbegiin foor ll:=11 too 9 do baccktrrackk(i,j,ll);endelsee Doo_Ouutpuut;ai,j:=0; ennd;注意斜體體的“aii,j:=00”必不可可少!當當對某個個結(jié)點(x,yy)擴展展的過程程中,可可能在擴擴展到(x+mm,y+n)時時它的子子樹被完完全殺死死(每個個結(jié)點都都被殺死死,亦即即按照(x,yy)及之之前的填填數(shù)方案案填數(shù),無解)。這時時需要保保證(xx,y)以后所所填的數(shù)數(shù)被重新新置零,這個語語句的作作用即在在每個結(jié)

25、結(jié)點被殺殺死時都都將其置置零。將偽代碼碼翻譯為為C+代碼:backktraack(intt i,intt j,intt k) innt ll; iif (cheeck(i,jj,k)=11) aiijj=kk; /Fiill in thee okkay sollutiion /GGeneeratte nnextt i,j if (j9) j+; eelsee i+; jj=1; /EEnd of Genneraate nexxt ii,j if (i10) foor (l=11;l=9;l+) baccktrrackk(i,j,ll); elsse ooutpput(); aiijj=00;

26、/*Whhen faiils andd gooes uppperwwardds, thee vaaluee muust be cleeareed*/ 函數(shù)ouutpuut()用雙重重循環(huán)完完成輸出出。在主主函數(shù)mmainn()對對baccktrrackk(1,1,ii)進行行一個循循環(huán),ii從1取取到9,即可完完成整個個程序。運行時時發(fā)現(xiàn)九九宮格的的解相當當多,即即使保存存到文件件中也不不現(xiàn)實。這就回回答了第第2個問問題。對于第11個問題題,將這這個程序序略加改改動,即即賦予全全局數(shù)組組a以初初值,并并在過程程baccktrrackk中產(chǎn)生生下一個個i和jj時跳過過有初值值的部分分,即可可將程

27、序序轉(zhuǎn)化為為求填有有部分空空缺的九九宮格程程序。最后給出出填充有有部分空空缺的九九宮格的的完整源源代碼。#inccludde usinng nnameespaace stdd;int a11111=00;int cheeck(intt i,intt j,intt k) innt ll,m,pi,pj; /1. Cheeck thee liine foor (l=11;l=9;l+) if ( (l!=j) & (ail!=0) & (aail=kk) ) rretuurn(0); /2. Cheeck thee coolummn foor (l=11;l=9;l+) if ( (l!=i) &

28、 (alj!=0) & (aalj=kk) ) rretuurn(0); /3. Cheeck thee 3xx3 mmatrrix /3.11 Fiirsttly we willl hhavee too chheckk thhe ppareent_i(ppi) andd paarennt_jj(pjj) iff (ii=33) ppi=11; ellse if (i=6) pii=4; ellse pi=7; iff (jj=33) ppj=11; ellse if (j=6) pjj=4; ellse pj=7; /3.22 Noow wwe ccan cheeck it foor (l=00;l=2;l+) ffor (m=0;mm=22;m+) iff ( (ppi+ll)!=i) & (ppj+mm)!=j) ) if ( ( api+lpj+m!=0 ) & ( api+lpj+m=k ) ) rretuurn(0); reeturrn(11); voiid ooutpput() innt ii,j; cooutOOne sollutiion is:enddl

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論