這幾天在學演算法,打算寫成部落格記下來加深一下印象,其中有什麼理解的不對或者寫錯的地方請點出。
第乙個是歸併排序,該演算法是分治法的典型應用,完全遵循分治模式,直觀的操作如下:
1.分解:分解待排序的n個元素的序列成兩個n/2的子串行。
2.解決:使用歸併排序遞迴地排序兩個子串行。
3.合併:合併兩個已排序的子串行以產生已排序的最終序列。
當分解到序列的長度為1時,遞迴開始回公升,此時長度為1的每個序列都是已經排好序的。
關鍵操作是合併兩個已經排好序的子陣列,該步驟通過乙個合併方法來完成,以玩撲克牌的例子,
假設桌上有兩堆已排序的撲克牌,最小的牌在上面,我們在這兩堆牌的最上面那一張中選取較小的牌,
將該牌取出,放到輸出堆。重複這個步驟,直到其中乙個堆空了,此時把另一堆剩下的牌也放在輸出堆,
由此,我們就把這兩堆牌合併成有序的一堆牌。該方法有4個引數,分別是乙個陣列和3個陣列的下標,
假設子陣列arr[p…q]和arr[q+1…r]已經排好序,其中p<=q
public static void merge(int arr, int p, int q, int r)
for (int j = 0; j < n2; j++)
int a = 0, b = 0;
for (int k = p; k <= r; k++)else
}if (a >= n1 && b < n2)
if (a < n1 && b >= n2)}}
接下來就是第一步分解和第二步解決了,遞迴排序的**實現如下:
public
static
void
megersort(int arr, int p, int r)
}
假設排序陣列[87,80,8,24,31,12,78,57,83,7]中的元素,9/2後兩個子陣列分為[87,80,8,24,31],[12,78,57,83,7],
針對左陣列[87,80,8,24,31],4/2後兩個子陣列分為[87,80,8],[24,31],2/2後兩個子陣列分為[87,80],[8],最後可以得到[87],[80]兩個
子陣列,此時兩個子陣列已經有序,而且不滿足p < r,進行回公升的過程,呼叫merge方法,得到有序陣列[80,87],接著合併[87,80],[8],
得到[8,80,87],合併[24],[31]得到,[24,31],然後合併[8,80,87],[24,31],得到[8,24,31,80,87],右陣列的過程也是如此,在這整個歸併排序
中,首先排序左陣列,當左陣列有序,接著排序右陣列,然後合併,重複這個過程直到排序完成。
演算法分析:
1. 時間複雜度
在歸併排序中可以看到,利用分治法的思想,每次都把問題分解為兩個原先問題的一半規模的子問題,所以原問題的時間為兩個子問題的和,由於它的形式就是一顆二叉樹,根據二叉樹可以得知它的時間複雜度為o(nlog2n)(以2為底)。
2. 空間複雜度
歸併排序不具有空間原址性(任何時候都只需要常數個額外的元素空間儲存臨時的資料),在合併的時候需要待合併元素數量大小的儲存空間。
測試:
public
接下來分別使用10000,100000,500000個隨機數進行測試:
歸併排序(一)
上兩篇部落格介紹了選擇排序插入排序和希爾排序 這次以我的理解來介紹一下歸併排序 在百科上面看到的概念 歸併排序 merge sort 是建立在歸併操作上的一種有效的排序演算法,該演算法是採用分治法 divide and conquer 的乙個非常典型的應用。將已有序的子串行合併,得到完全有序的序列 ...
歸併排序(2 路歸併排序)
遞迴寫法 include define maxn 100 void merge int a,int l1,int r1,int l2,int r2 將陣列a的區間 l1,r1 和區間 l2,r2 合併為乙個有序區間 else while i r1 while j r2 for int i 0 i非遞...
python歸併排序 python 歸併排序
排序思路 1.將陣列分成兩組a,b,建立臨時陣列 c,c長度 a b 2.i,j分別屬於a,b 3.若a i b j 將b j 放入c,j 否則 a i 放入c,i 4.迴圈3步驟,將a或b中剩餘的元素放入c,再將c複製到陣列中 5.遞迴3 4直到a,b序列的長度 1 歸併排序 class merg...