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

歡迎訪問 生活随笔!

生活随笔

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

综合教程

C/C++ 递归

發(fā)布時(shí)間:2023/10/11 综合教程 91 老码农
生活随笔 收集整理的這篇文章主要介紹了 C/C++ 递归 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

遞歸

當(dāng)一個(gè)函數(shù)調(diào)用它自己來定義時(shí)稱它為遞歸函數(shù)。(什么叫它自己調(diào)用它自己呢?)

1.1、引出遞歸

從一個(gè)簡單的問題考慮遞歸,求0,1,2, 3,4,5......n的和。

首先定義一個(gè)求和公式:sum(n);

顯然對于(n > 0): sum(n) = sum(n - 1) + n ;

? (n = 0 ) : sum(0) = 0;

? 成立。

將上述公式翻譯成C++函數(shù):

unsigned int sum(unsigned int n)
{
if(0 == n)
{
return 0; //基準(zhǔn)情況(遞歸的出口),sum不能一直調(diào)用它自己吧,總歸要有一個(gè)出口結(jié)束遞歸吧
}
else
{
return sum(n - 1) + n; //sum(unsigned int)調(diào)用了它自己
}
}

假設(shè) n = 5 分析一下計(jì)算過程:

sum(5) = sum(4) + 5;

sum(4) = sum(3) + 4;

sum(3) = sum(2) + 3;

sum(2) = sum(1) + 2;

sum(1) = sum(0) + 1;

sum(0) = 0; 當(dāng)sum(0)時(shí),sum()不再調(diào)用它自己,作為遞歸的出口結(jié)束遞歸。

假設(shè)沒有n = 0, sum(0) = 0 這個(gè)基準(zhǔn)情況作為遞歸的出口跳出遞歸,遞歸就會(huì)一直遞歸下去,沒完沒了直至崩潰。因此遞歸函數(shù)必須有一個(gè)基準(zhǔn)情況作為遞歸出口

1.2、失敗的遞歸

給出一個(gè)所謂的遞歸函數(shù):

int bad(unsigned int n)
{
if(0 == n)
{
return 0;
}
else
{
return bad(n/3 + 1) + n - 1;
}
}

分析一下以上函數(shù),函數(shù)給出了 n = 0 的情況作為遞歸的出口,看似沒什么問題。

還是假設(shè)n = 5;

bad(5) : 調(diào)用bad(5/3 + 1), 即bad(2);

bad(2) : 調(diào)用bad(2/3 + 1), 即bad(1);

bad(1) : 調(diào)用bad(1/3 + 1), 即bad(1);

bad(1) : 調(diào)用bad(1/3 + 1), 即bad(1)..........

bad(1)一直調(diào)用bad(1), 一直調(diào)用到程序崩潰。很明顯bad()函數(shù)定義雖然給出了 n = 0 作為遞歸出口,但是bad()函數(shù)根本不會(huì)推進(jìn)到n = 0 的這種情況。因此遞歸調(diào)用必須總能夠朝著產(chǎn)生基準(zhǔn)情況(遞歸出口)的方向推進(jìn)

1.3、遞歸和歸納

考慮一個(gè)問題:現(xiàn)在需要將一個(gè)正整數(shù) n 打印出來,但是I/O給出的函數(shù)接口(printDigit)只能處理單個(gè)數(shù)字(即n < 10)。

我們隨便假設(shè)一個(gè)n值:n = 2019,那么單個(gè)數(shù)字打印的順序就是2, 0, 1, 9。換句話說,9是最后一個(gè)打印的,在打印9之前要先打印201,即先打印“201”,再打印“9”;依次類推對于“201”先打印“20”,再打印“1”;對于“20”先打印“2”,再打印“0”;對于2已經(jīng)是單個(gè)數(shù)字,可以直接打印了, 不需要再劃分,再遞歸了,也就是說單個(gè)數(shù)字n < 10即為遞歸的出口。

我們按上述思路細(xì)致的分析一下:

對2019分成2部分: 201 = 2019 / 10; 9 = 2019 % 10;

對201分成2部分:20 = 201 / 10; 1 = 201 % 10;

對20分成2部分:2 = 20 / 10; 0 = 20 % 10;

對于 2 滿足 n < 10 的條件,不再遞歸,直接打印。

現(xiàn)在遞歸已經(jīng)很明顯了,嘗試編寫一下代碼:

//假設(shè)printDigit((unsigned int n)如下,
void printDigit(unsigned int n)
{
std::cout << n;
} void print(unsigned int n)
{
if(n >= 10)
{
print(n / 10);
}
printDigit(n % 10);
}

代碼編寫好了,現(xiàn)在需要證明以下代碼是否正確:對于n >= 0,數(shù)的遞歸打印算法總是正確的。

證明:用k表示數(shù)字n的包含單個(gè)數(shù)字的個(gè)數(shù)。當(dāng)k = 1,即 n < 10 時(shí),很明顯程序是正確的,因?yàn)樗恍枰f歸,print()只調(diào)用一次printDigit(), 不調(diào)用它自己。然后假設(shè)print()對于所有k位數(shù)都能正常工作,任何k + 1位的數(shù)字n都可以通過它的前k位的數(shù)字和最低1位數(shù)字來表示。前k 位的數(shù)字恰好是[ n / 10], 歸納假設(shè)它能正常工作,而最低1位數(shù)字是[ n % 10],因此該程序能夠正確的打印出任意k + 1位。于是根據(jù)歸納法[1],所有數(shù)字都能被正確打印出來。

由以上實(shí)例總結(jié)可以出一條遞歸的設(shè)計(jì)法則:假設(shè)所有遞歸調(diào)用都能運(yùn)行。

1.4、遞歸的合成效益法則

用遞歸實(shí)現(xiàn)一個(gè)斐波那契數(shù)列:

//斐波納契數(shù)列:1、1、2、3、5、8、13、21、34
int f(int n)
{
if(n < 1)
{
return 0;
}
else if(n <= 2)
{
return 1;
} return f(n-1) + f(n-2); }

假設(shè)n = 8, 函數(shù)調(diào)用f(8), 遞歸調(diào)用如下圖:

graph TB
8-->7;
7-->6;
6-->5;
5-->4;
4-->3;
3-->2;
8-->id0(6);
id0(6)-->id1(5);
id1(5)-->id2(4);
id2(4)-->id3(3);
id3(3)-->id4(2);
7-->id5(5);
id5(5)-->id6(4);
id6(4)-->id7(3);
id7(3)-->id8(2);
6-->id9(4);
id9(4)-->id10(3);
id10(3)-->id11(2);
5-->id12(3);
id12(3)-->id13(2);
4-->id14(2);
3-->id15(1);
id12(3)-->id16(1);
id9(4)-->id17(2);
id10(3)-->id18(1);
id5(5)-->id19(3);
id19(3)-->id20(2);
id19(3)-->id21(1);
id6(4)-->id22(2);
id7(3)-->id23(1);
id0(6)-->id24(4);
id24(4)-->id25(3);
id24(4)-->id28(2);
id25(3)-->id26(2);
id25(3)-->id27(1);
id1(5)-->id29(3);
id29(3)-->id30(2);
id29(3)-->id31(1);
id2(4)-->id32(2);
id3(3)-->id33(1);

由上圖我們不厭其煩的數(shù)一下:

n = 1時(shí),f()調(diào)用1次;

n = 2時(shí),f()調(diào)用1次;

n = 3時(shí),f()調(diào)用3次;

n = 4時(shí),f()調(diào)用5次;

n = 5時(shí),f()調(diào)用9次;

n = 6時(shí),f()調(diào)用15次;

n = 7時(shí),f()調(diào)用25次;

n = 8時(shí),f()調(diào)用41次;

增長的是不是太快了,在f()里加一個(gè)計(jì)數(shù)器測試一下,可以看到在n = 30 的時(shí)候,f()的調(diào)用次數(shù)大約在160萬。

究其原因,是因?yàn)槲覀冊谇蠼獾倪^程時(shí),重復(fù)了大量的計(jì)算過程, 在n = 8 的時(shí)候單單是f(3)就重復(fù)調(diào)用了8次。

由上我們可以得出一個(gè)結(jié)論:在求解一個(gè)問題的同一實(shí)例時(shí),在不同的遞歸中做重復(fù)性的工作,對資源的消耗可能是災(zāi)難性的。

最后歸納一下要牢記的遞歸四條基本法則:

  1. 基準(zhǔn)情形。必須總有某些基準(zhǔn)情況,它無須遞歸就能求解,即遞歸必須有出口。
  2. 不斷推進(jìn)。對于那些需要遞歸求解的情形,每一次遞歸調(diào)用都必須要使求解狀態(tài)朝基準(zhǔn)情形的方向推進(jìn)。
  3. 設(shè)計(jì)法則。假設(shè)所有的遞歸調(diào)用都能運(yùn)行。
  4. 合成效益法則。在求解一個(gè)問題的同一實(shí)例時(shí),切勿在不同的遞歸中做重復(fù)性的工作。

  1. 1、證明當(dāng)n= 1時(shí)命題成立。2、假設(shè)n=m時(shí)命題成立,那么可以推導(dǎo)出在n=m+1時(shí)命題也成立。(m代表任意自然數(shù))。3、歸納結(jié)論。 ??

總結(jié)

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

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

主站蜘蛛池模板: 激情久久婷婷 | 久久久久久久久久久91 | 亚洲成人久久久 | 日韩av在线导航 | 国产精品视频在线观看免费 | 亚洲第一成肉网 | av网子| 亚洲欧美精品一区 | 色综合天 | www.com黄色| 精品一区二区在线视频 | 熟女毛毛多熟妇人妻aⅴ在线毛片 | 中文字幕av高清 | 欧美三级在线看 | 天天爽影院 | 日本久久久久久久久久 | 免费成人进口网站 | 精品人妻一区二 | 成人黄色片免费 | av手机| 黑人欧美一区二区三区 | 波多野结衣在线观看一区 | 欧美精品video | www.haoav| 日本免费无人高清 | 怡红院院av | 成人小视频免费 | 久久视频在线 | 激情宗合| 超碰碰97 | 花房姑娘免费全集 | 荫蒂被男人添免费视频 | 久久九九爱 | 国产xx视频 | 国产精品免费久久久久 | 狠狠干夜夜草 | 强制高潮抽搐哭叫求饶h | 香蕉视频在线观看视频 | 熟妇的味道hd中文字幕 | 欧美丰满熟妇xxxx | 成人黄色短片 | 男人的天堂国产 | hitomi一区二区三区精品 | 永久免费国产 | 欧美中日韩在线 | 青青操免费在线视频 | 国产乱码精品一区二三区蜜臂 | 快射视频在线观看 | 成人黄色一区二区三区 | 国产女人18水真多毛片18精品 | 日本中出视频 | 亚洲精品一线 | 裸体一区二区 | 国产精品视频一 | 在线网站av | 天天视频国产 | 亚洲av熟女国产一区二区性色 | 亚洲成人网在线观看 | 亚洲一区 欧美 | 超碰97在线看 | 卡一卡二卡三 | 黄色片99 | 国产91香蕉 | 亚洲国产一级 | 91青青操 | 国产在线视频资源 | 国产精品36p | 免费污片软件 | 国产又粗又大又黄 | 黄色一级视频网站 | 西比尔在线观看完整视频高清 | 亚洲综合另类小说 | 黄视频免费看在线 | 成人午夜精品一区二区三区 | 国产亚洲av综合人人澡精品 | 日韩欧美精品在线视频 | www.欧美国产 | 亚洲久久成人 | 久久久久久黄色 | 自拍偷拍视频在线观看 | 国产天堂精品 | 变态另类ts人妖一区二区 | 成人免费大全 | 国产精品免费视频一区 | 成人女同av免费观看 | 五月婷婷视频 | 精品国产99一区二区乱码综合 | avwww.| av伊人久久 | 爱情岛论坛亚洲品质自拍 | 成人亚洲黄色 | 小早川怜子一区二区三区 | 琪琪射| 老师上课夹震蛋高潮了 | 久久久欧美 | 日韩国产欧美一区二区 | 亚洲国产精品第一页 | 中文天堂资源在线 | 免费亚洲视频 |