算法中的递归分析和分治法的原理
顯然,分解容易(一分為二),組合難。
快速排序?
剛剛分析過(guò)了,快速排序是樞軸記錄劃分,也就是分解難,但是組合易。?? A[1…k-1] ≤ A[k] ≤ A[k+1…n]
分治算法分析 設(shè)T(n)是Size為n的執(zhí)行時(shí)間,若Size足夠小,如n ≤ C (常數(shù)),則直接求解的時(shí)間為θ(1) ①設(shè)完成劃分的時(shí)間為D(n) ②設(shè)分解時(shí),劃分為a個(gè)子問(wèn)題,每個(gè)子問(wèn)題為原問(wèn)題的1/b,則解各子問(wèn)題的時(shí)間為aT(n/b) ③設(shè)組合時(shí)間C(n) 一般地,遞歸的求解劃分,而解遞歸式時(shí)可忽略細(xì)節(jié) ①假定函數(shù)參數(shù)為整數(shù),如 ②邊界條件可忽略,當(dāng)n較小時(shí),T(n)=?θ(1)因?yàn)檫@些細(xì)節(jié)一般只影響常數(shù)因子的大小,不改變量級(jí)。求解時(shí),先忽略細(xì)節(jié),然后再?zèng)Q定其是否重要!
分析的方法
替換法
猜測(cè)解,用數(shù)學(xué)歸納法確定常數(shù)C,證明解正確,關(guān)鍵步驟是用猜測(cè)的解代入到遞歸式中。 做出好的猜測(cè)(沒(méi)有一般方法,只能憑經(jīng)驗(yàn)) ①與見(jiàn)過(guò)的解類似,則猜測(cè)之。 ②先證較寬松的上、下界,減小猜測(cè)范圍。 細(xì)節(jié)修正 有時(shí)猜測(cè)解是正確的,但數(shù)學(xué)歸納法卻不能直接證明其細(xì)節(jié),這是因?yàn)閿?shù)學(xué)歸納法不是強(qiáng)大到足以證明其細(xì)節(jié)。這時(shí)可從猜測(cè)解中減去一個(gè)低階項(xiàng)以使數(shù)學(xué)歸納法得以滿足 避免陷阱 與求和式的數(shù)學(xué)歸納法類似,證明時(shí)漸近記號(hào)的使用易產(chǎn)生錯(cuò)誤。 變量變換 有時(shí)改動(dòng)變量能使未知遞歸式變?yōu)槭煜さ氖阶印@?#xff1a; 迭代法 展開(kāi):無(wú)須猜測(cè),展開(kāi)遞歸式,使其成為僅依賴于n和邊界條件的和式,然后用求和方法定界。需要關(guān)注: 1、達(dá)到邊界條件所需的迭代次數(shù) 2、迭代過(guò)程中的和式。若在迭代過(guò)程中已估計(jì)出解的形式,亦可用替換法 3、當(dāng)遞歸式中包含floor和ceiling函數(shù)時(shí),常假定參數(shù)n為一個(gè)整數(shù)次冪,以簡(jiǎn)化問(wèn)題。 遞歸樹(shù) 使展開(kāi)過(guò)程直觀化 例: T(n)=2T(n/2)+n^2?? (不妨設(shè)n=2k)The master method(通用法,萬(wàn)能法)
可迅速求解
T(n)=aT(n/b)+f(n)?? //常數(shù)a ≥1, b>1, f(n)漸近正 意義:將Size為n的問(wèn)題劃分為a個(gè)子問(wèn)題,每個(gè)子問(wèn)題Size為n/b。每個(gè)子問(wèn)題的時(shí)間為T(n/b),劃分和combine的時(shí)間為f(n)。 注意:n/b不一定為整數(shù),應(yīng)為?n/b?或?n/b?,不會(huì)影響漸近界。 ? 關(guān)于遞歸和循環(huán)的理解與比較遞歸通俗的說(shuō)就是一個(gè)函數(shù)調(diào)用函數(shù)自己(本身),這個(gè)調(diào)用過(guò)程叫遞歸,遞歸是一把雙刃劍(有時(shí)方便,有時(shí)不好),如果需要處理重復(fù)的需要多次計(jì)算的問(wèn)題,通常可以選擇用遞歸或者循環(huán)兩種方式,但是遞歸的執(zhí)行效率不如循環(huán)語(yǔ)句。
注意:必須設(shè)置終止遞歸的條件檢測(cè),否則慎用。
void up_and_down(int);//函數(shù)原型聲明int main() {up_and_down(1);//調(diào)用遞歸函數(shù)
system("pause");
return 0; }
void up_and_down(int n) {printf("level%d, n地址=%p\n", n, &n);if (n < 4){up_and_down(n + 1);}printf("LEVEL%d, n地址=%p\n", n, &n); }
首先,main函數(shù)用參數(shù)1調(diào)用遞歸函數(shù),遞歸函數(shù)形參n=1,打印語(yǔ)句level1……然后,n<4,故函數(shù)本身使用參數(shù)n+1=2,第二次調(diào)用自己,這樣就打印了level2……
以此類推,當(dāng)執(zhí)行到第四級(jí)調(diào)用,n=4,if失效,不再調(diào)用函數(shù),而是執(zhí)行了第二句打印,先輸出LEVEL4……此時(shí)第四級(jí)調(diào)用結(jié)束,控制權(quán)返回給了主調(diào)函數(shù),也就是第三級(jí)主調(diào)函數(shù),此函數(shù)中上一句是if語(yǔ)句,已經(jīng)執(zhí)行完畢,然后繼續(xù)執(zhí)行第二句打印語(yǔ)句,輸出LEVEL3……第三級(jí)調(diào)用結(jié)束,返回控制權(quán)給調(diào)用函數(shù)(也就是第二級(jí)主調(diào)函數(shù)),然后第二級(jí)函數(shù)開(kāi)始繼續(xù)執(zhí)行,以此類推,打印LEVEL2,1……
遞歸的基本原理
每一級(jí)遞歸都使用自己這一級(jí)的私有變量n,同級(jí)調(diào)用時(shí)的地址和返回的地址是一樣的。好好揣摩!
這是函數(shù)自己在一層層的往深度調(diào)用自己,然后一層層的往回返,每到一層,就繼續(xù)執(zhí)行接下來(lái)的語(yǔ)句(故調(diào)用開(kāi)始的地址和返回的地址一樣),而每一級(jí)遞歸都是用自己的局部變量。也就是第一級(jí)的n不同于第二級(jí)的n,這樣子,函數(shù)逐步調(diào)用然后逐步返回直到main函數(shù)里。
遞歸函數(shù)里,遞歸語(yǔ)句之前的語(yǔ)句和各級(jí)被調(diào)的遞歸函數(shù)執(zhí)行順序一致,而遞歸語(yǔ)句之后的語(yǔ)句和被調(diào)的遞歸函數(shù)執(zhí)行順序相反(這一特點(diǎn)針對(duì)涉及反向順序的編程問(wèn)題很有用)?
遞歸函數(shù)必須包含可以終止的條件,因?yàn)檫f歸可以替代循環(huán),故必須有終止
尾遞歸
最簡(jiǎn)單的遞歸:遞歸語(yǔ)句放到函數(shù)末尾,恰在return語(yǔ)句前,叫做tail recursion(尾遞歸),因?yàn)槌霈F(xiàn)在函數(shù)尾部,作用相當(dāng)于一條循環(huán)語(yǔ)句。
//計(jì)算階乘(遞歸和循環(huán)) #include <stdio.h> #include <stdlib.h> //計(jì)算階乘 int factorial(int); int loopFactorial(int);int main() {int num;printf("輸入1-12的整數(shù),q退出\n");while (scanf_s("%d", &num)){if (num < 0){printf("error!輸入1-12的整數(shù)!");}else if (num > 12){printf("輸入1-12的整數(shù)!");}else{printf("\n%d的階乘=%d", num, factorial(num));printf("\n%d的階乘=%d", num, loopFactorial(num));}printf("\n輸入1-12的整數(shù)");}system("pause");return 0; } //循環(huán)計(jì)算階乘 int factorial(int n) {int temp;for (temp = 1; n > 1; n--){temp *= n;}return temp; } //使用遞歸計(jì)算階乘 int loopFactorial(int n) {int temp;if (n > 0){temp = n * loopFactorial(n - 1);//屬于尾遞歸,如n>0那么這就是最后一句 }else{temp = 1;//必須要有遞歸結(jié)束判斷條件! }return temp; }注意:整型范圍,32位機(jī)器,int類型最大到21多億,再大的話,就要用long long或者double類型,一般來(lái)說(shuō),選擇循環(huán)比較好些,遞歸每次調(diào)用都要有自己的變量集合,占據(jù)內(nèi)存大,每次都要存儲(chǔ)新的變量集合到堆棧,這樣速度慢,但是遞歸(最簡(jiǎn)單的是尾遞歸)比較簡(jiǎn)單。一些情況還是要用。
?
總結(jié)
以上是生活随笔為你收集整理的算法中的递归分析和分治法的原理的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 做点什么吧
- 下一篇: 优化神器 beamoff