西西軟件園多重安全檢測(cè)下載網(wǎng)站、值得信賴的軟件下載站!
軟件
軟件
文章
搜索

首頁(yè)編程開發(fā)其它知識(shí) → 遞歸轉(zhuǎn)化成循環(huán)的算法實(shí)現(xiàn)

遞歸轉(zhuǎn)化成循環(huán)的算法實(shí)現(xiàn)

相關(guān)軟件相關(guān)文章發(fā)表評(píng)論 來(lái)源:本站整理時(shí)間:2011/2/12 9:03:15字體大。A-A+

作者:佚名點(diǎn)擊:214次評(píng)論:0次標(biāo)簽: 遞歸 循環(huán)

  • 類型:源碼相關(guān)大。34KB語(yǔ)言:中文 評(píng)分:5.0
  • 標(biāo)簽:
立即下載
 有些遞歸是很容易轉(zhuǎn)化成循環(huán)的,用一個(gè)循環(huán)非常直觀的映射過(guò)去就是了,如求Fibonacci數(shù)列; 而有些遞歸卻沒(méi)有那么直觀,甚至可能需要多個(gè)循環(huán)才能轉(zhuǎn)化過(guò)去,這里舉個(gè)例子:

給出一個(gè)集合,如(1, 2, 3, 4),打印出該集合的所有子集
分析一下問(wèn)題,子集是指取原集合中的任意多個(gè)元素,轉(zhuǎn)化一下問(wèn)題,就是對(duì)于原集合中的任何一個(gè)元素,我們都有兩個(gè)選擇,包含或者不包含,所以對(duì)于n個(gè)元素的集合,其子集數(shù)為: 2*2*2... = 2^n。那么可以得出其遞歸算法:

01 void Recursive_Subsets(int* a, bool* b, int start, int end)

02 {

03 if (start <= end)

04 {

05 // determine current number's status, which has 2 choices

06 // and then continue with left ones

07 b[start] = true;

08 Recursive_Subsets(a, b, start+1, end);

09

10 b[start] = false;

11 Recursive_Subsets(a, b, start+1, end);

12 }

13 else

14 {

15 for (int i = 0; i <= end; i++)

16 {

17 if (b[i]) cout << a[i];

18 }

19 cout << endl;

20 }

21

22 }

23

24 void PrintAllSubsets1(int* a, int n)

25 {

26 bool* b = new bool[n];

27 Recursive_Subsets(a, b, 0, n-1);

28 delete b; 
29 }

遞歸的優(yōu)點(diǎn)是直觀、易懂:寫起來(lái)如此,讀起來(lái)也是這樣。但是每次遞歸都是call stack的不斷疊加,對(duì)于這個(gè)問(wèn)題,其需要消耗O(n)的?臻g,?臻g,?臻g~~~

于是,我們也可以將其轉(zhuǎn)化成循環(huán)的方式來(lái)實(shí)現(xiàn):

01 void PrintAllSubsets2(int* a, int n)

02 {

03 // Initialize flags as false

04 bool* b = new bool[n];

05 for(int i = 0; i < n; i++)

06 {

07 b[i] = false;

08 }

09

10 // Use 2 loops to enumerate all possible combinations of (each item's status * number of items),

11 // in this case: ([true|false] * size of set)

12 while(true)

13 {

14 // Get one solution, output it!

15 for(int i = 0; i < n; i++)

16 {

17 if(b[i]) cout << a[i];

18 }

19 cout << endl;

20

21

22 // One of the number's status has switched, start over enumeration for that!

23 // ex: I have following enumeration for 3 numbers:

24 // 0, 0, 0

25 // 0, 0, 1

26 // 0, 1, 0

27 // 0, 1, 1

28 // now if I changed the first number's status from 0 to 1, I need to re-enumerate the other 2 numbers

29 // to get all possible cases:

30 // 1, 0, 0

31 // 1, 0, 1

32 // 1, 1, 0

33 // 1, 1, 1

34 int k = n - 1;

35

36 while(k >= 0)

37 {

38 if(b[k] == false) // have we tried all possible status of k?

39 {

40 b[k] = true; // status switch, as we only have 2 status here, I use a boolean rather than an array.

41 break; // break to output the updated status, and further enumeration for this status change, just like a recursion

42 }

43 else // We have tried all possible cases for k-th number, now let's consider the previous one

44 {

45 b[k] = false; // resume k to its initial status

46 k--; // let's consider k-1

47 }

48 }

49

50 if(k < 0) break; // all the numbers in the set has been processed, we are done!

51 }

52

53 // clean up

54 delete [] b;

55 }

詳細(xì)如何轉(zhuǎn)換在注釋中已經(jīng)說(shuō)明,對(duì)于這類窮舉狀態(tài)的遞歸程序,我們可以將這個(gè)程序的框架當(dāng)做一個(gè)模式,照樣子來(lái)轉(zhuǎn)化即可。

    相關(guān)評(píng)論

    閱讀本文后您有什么感想? 已有人給出評(píng)價(jià)!

    • 8 喜歡喜歡
    • 3 頂
    • 1 難過(guò)難過(guò)
    • 5 囧
    • 3 圍觀圍觀
    • 2 無(wú)聊無(wú)聊

    熱門評(píng)論

    最新評(píng)論

    發(fā)表評(píng)論 查看所有評(píng)論(0)

    昵稱:
    表情: 高興 可 汗 我不要 害羞 好 下下下 送花 屎 親親
    字?jǐn)?shù): 0/500 (您的評(píng)論需要經(jīng)過(guò)審核才能顯示)