由合併排序演算法談如何理解遞迴

2021-06-17 16:20:43 字數 1776 閱讀 2094

今天早上突然來了興致,拿起了塵封多月的《演算法導論》翻看起來,正好看到合併排序一章,看完介紹後自己動手程式設計實現,經過簡單的除錯糾錯後程式正確執行,但是細細一品其中用到的遞迴知識,感覺糊里糊塗,有種只知表面不知根源的感覺。上網查閱相關資料發現有部分朋友跟我有同樣地感受,不知道遞迴的原理究竟是什麼,經過我苦思冥想後,決定用一種通俗易懂但也許並不符合科學的方式理解遞迴,寫這篇文章的目的就是和大家一起交流關於遞迴的經驗,共同進步。

merge_sort(a,p,r)

if p < r

then q ← 下取整[(p + r) / 2]

merge_sort(a,p,q)

merge_sort(a,q+1,r)

merge(a,p,q,r)

其中,merge_sort是分解過程的函式,merge是合併過程的函式;a存放待排序數列,p是操作序列起點序號,r是操作序列終點序號。

我們用一種樹的概念來理解,由於這個遞迴是雙向的,類似於二叉樹。遞迴一定有乙個終止條件,不到達這個終止條件遞迴是不會停止。如果到達了終止條件,遞迴就會返回上一層,利用上一層的變數進行相關操作。如果上一層還有其他路徑的遞迴,則按照其他路徑一路遞迴到底,然後返回,在逐層返回的過程中,在每層利用該層的變數完成相關的操作。說了一些晦澀難懂的文字,想必大家一定看著頭暈,下面結合例項予以進一步的解釋:

從圖中可以看到,假如我們一開始的函式是merge_sort(a,0,2),那麼程式就會一直將merge_sort(a,p,r)執行到底,即merge_sort(a,0,2)→merge_sort(a,0,1)→merge_sort(a,0,0),直到執行到merge_sort(a,0,0)時,滿足推出條件,這是程式返回上一層(圖中所示2層),這一層的引數是p=0,r=1,q=0,這一層下一條語句是merge_sort(a,q+1,r),即merge_sort(a,1,1),其實這條語句在圖中反應的就是由2層走右側路徑到達3層,由於滿足退出條件所以再次返回2層,接下來執行2層的最後一條語句merge(a,p,q,r),即merge(a,0,0,1)。執行完這條語句後,左側2層的任務結束,返回一層,一層的變數是p=0,r=2,q=1。由於1層已經執行完成了第一條語句,所以1層要執行第二條語句,即merge_sort(a,q+1,r),即merge_sort(a,2,2),滿足退出條件,再次返回1層,接下來執行1層的merge(a,0,1,2)後,程式結束,完成合併排序的功能。

由於合併排序有兩個遞迴函式,所以該程式的執行路徑類似於二叉樹的遍歷過程。其實,好多程式只涉及到乙個遞迴,為了加強理解,我們再舉一例:

考慮如下遞迴程式,最終的輸出是多少?

void a(int num)

if(num > 0)

num -- ;

a(num) ;

printf("%d " , num);

main()

a(4) ;

system("pause");

return 0 ;

輸出結果:0 1 2 3

按照之前所說,我們先畫出遞迴樹,寫出每一層的變數值,按照先遞迴到底再逐層返回的步驟分析:

由圖分析,當執行a(4)時,會直接遞迴到底a(4)→a(3)→a(2)→a(1)→a(0),遞迴到a(0)後由於滿足遞迴退出條件所以逐層向上返回,由於每一層的第一(num--)、第二(a(i))語句已經執行完畢,所以每當返回到某一層是,就會根據該層的num值列印出相應結果,所以最終的輸出結果時0 1 2 3。

看了兩個例子,大家是不是已經有了一些想法啊,浣熊在這裡總結一下:如果遇到遞迴,如果沒有達到遞迴條件,就要一直遞迴到底;遞迴到底後,逐層返回,到每一層時,利用該層的變數值去執行遞迴語句的下一條語句,直到返回到根節點的一層,程式結束。

遞迴實現合併排序

subject 計算機演算法設計與分析 title 2.7.1 遞迴實現合併排序 coder hao class 計科0906 num 0304090614 date sept 25th,2011 includeusing namespace std 用於合併的函式 template void me...

歸併排序(合併排序) 遞迴法

參考了一些大佬的 再自己總結了一下。原理基本不變。歸併排序 合併排序 是一種分治演算法。這個演算法不斷地將乙個陣列分為兩部分,分別對左子陣列和右子陣列排序,然後將兩個陣列合併為新的有序陣列。穩定 是 時間複雜度 最優 o nlog n 最差 o nlog n 平均 o nlog n include ...

排序(2)歸併排序(遞迴 合併排序)

用到遞迴 合併,所以叫歸併。public static int data 遞迴 param temp 臨時陣列 param sindex 開始索引 param eindex 結束索引 private static void recursion int temp,int sindex,int eind...