本文實(shí)例講述了Java分治歸并排序算法。分享給大家供大家參考,具體如下:
1、分治法
許多有用的算法在結(jié)構(gòu)上是遞歸的:為了解決一個(gè)給定的問題,算法一次或多次遞歸地調(diào)用其自身以解決緊密相關(guān)的若干子問題。這些算法典型地遵循分治法的思想:將原問題分解為幾個(gè)規(guī)模較小但類似于原問題的子問題,遞歸地求解這些子問題,然后再合并這些子問題的解來建立原問題的解。
分治模式在每層遞歸時(shí)都有三個(gè)步驟:
(1)分解原問題為若干子問題,這些子問題是原問題的規(guī)模較小的實(shí)例。
(2)解決這些子問題,遞歸地求解各子問題。然而,若子問題的規(guī)模足夠小,則直接求解。
(3)合并這些子問題的解成原問題的解。
2、歸并排序算法
歸并排序算法完全遵循分治模式。直觀上其操作如下:
(1)分解:分解待排序的n個(gè)元素的序列成各具n/2個(gè)元素的兩個(gè)子序列。
(2)解決:使用歸并排序遞歸地排序兩個(gè)子序列。
(3)合并:合并兩個(gè)已排序的子序列以產(chǎn)生已排序的答案。
當(dāng)待排序的序列長度為1時(shí),遞歸“開始回升”,在這種情況下不要做任何工作,因?yàn)殚L度為1的每個(gè)序列都已排好序。歸并排序算法的關(guān)鍵操作是“合并”步驟中兩個(gè)已排序序列的合并。我們通過調(diào)用一個(gè)輔助過程Merge(A,p,q,r)來完成合并,其中A是一個(gè)數(shù)組,p、q和r是數(shù)組下標(biāo),滿足p<=q<r。該過程假設(shè)子數(shù)組A[p,q]和A[q+1,r]都已排好序。它合并這兩個(gè)子數(shù)組形成單一的已排好序的子數(shù)組并代替當(dāng)前的子數(shù)組A[p,r]。
過程Merge按以下方式工作?;氐轿覀兺鎿淇伺频睦樱僭O(shè)桌上有兩堆牌面朝上的牌,每堆都已排序,最小的牌在頂上。我們希望把這兩堆牌合并成單一的排好序的輸出堆,牌面朝下地放在桌上。我們的基本步驟包括在牌面朝上的兩堆牌的頂上兩張牌中選取較小的一張,將該牌從其堆中移開(該堆的頂上將顯露一張新牌)并牌面朝下地將該牌放置到輸出堆。
下面是Merge的偽代碼:
Merge(A,p,q,r):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
tmp[ 1 ,..,r-p+ 1 ] i = p j = q+ 1 while i <= q && j <= r if A[i] <= A[j] tmp[k++] = A[i++]; else tmp[k++] = A[j++]; while i <= q tmp[k++] = A[i++]; while j <= r tmp[k++] = A[j++]; for k2 = 0 to tmp.length A[k2+p] = tmp[k2]; |
現(xiàn)在我們可以把過程Merge作為歸并排序算法中的一個(gè)子程序來用。下面的過程Merge_sort(A,p,r)排序子數(shù)組A[p,r]中的元素。若p>=r,則該子數(shù)組最多有一個(gè)元素,所以已經(jīng)排好序。否則,分解步驟簡單地計(jì)算一個(gè)下標(biāo)q,將A[p,r]分成兩個(gè)子數(shù)組A[p,q]和A[q+1,r],前者包含[n/2]個(gè)元素,后者包含[n/2]個(gè)元素。
1
2
3
4
5
6
|
Merge_sort(A,p,r): if p < r q = (p+r)/ 2 Merge_sort(A,p,q) Merge_sort(A,q+ 1 ,r) Merge(A,p,q,r) |
為了排序整個(gè)序列A=(A[0],A[1],...,A[n]),我們執(zhí)行初始調(diào)用Merge_sort(A,0,A.length),這里再次有A.length = n。圖2-4自底向上地說明了當(dāng)n為2的冪時(shí)該過程的操作。算法由以下操作組成:合并只含1項(xiàng)的序列對形成長度為2的排好序的序列,合并長度為2的序列對形成長度為4的排好序的序列,依此下去,直到長度為n/2的兩個(gè)序列被合并最終形成長度為n的排好序的序列。
3、Java代碼實(shí)現(xiàn)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
|
public class Merge_sort_test { public static void Merge( int [] A, int p, int q, int r){ int [] tmp = new int [r-p+ 1 ]; //聲明一個(gè)臨時(shí)數(shù)組,長度為要?dú)w并數(shù)組的長度 int i = p; //記住左邊數(shù)組第一個(gè)元素的下標(biāo) int j = q+ 1 ; //記住右邊數(shù)組第一個(gè)元素的下標(biāo) int k = 0 ; while (i <= q && j <= r){ //左邊數(shù)組元素和右邊數(shù)組元素比較,把小的元素賦給臨時(shí)數(shù)組 if (A[i] <= A[j]){ tmp[k++] = A[i++]; } else { tmp[k++] = A[j++]; } } //把左邊剩余的數(shù)組元素賦給臨時(shí)數(shù)組 while (i <= q){ tmp[k++] = A[i++]; } //把右邊剩余的數(shù)組元素賦給臨時(shí)數(shù)組 while (j <= r){ tmp[k++] = A[j++]; } //用臨時(shí)數(shù)組元素覆蓋原數(shù)組元素 for ( int k2 = 0 ;k2 < tmp.length;k2++){ A[k2+p] = tmp[k2]; } } public static void /*int[]*/ Merge_sort( int [] A, int p, int r){ int q = (p+r)/ 2 ; if (p < r){ //遞歸調(diào)用 Merge_sort(A,p,q); Merge_sort(A,q + 1 ,r); //歸并排序數(shù)據(jù)元素 Merge(A,p,q,r); } //return A; } public static void main(String[] args) { // int [] A = { 5 , 2 , 4 , 7 , 1 , 3 , 2 , 6 }; System.out.println( "原始數(shù)據(jù): " ); for ( int i = 0 ;i < A.length;i++){ System.out.print(A[i] + " " ); } System.out.println(); Merge_sort(A, 0 ,A.length - 1 ); System.out.println( "輸出結(jié)果: " ); for ( int i = 0 ;i < A.length;i++){ System.out.print(A[i] + " " ); } } } |
希望本文所述對大家java程序設(shè)計(jì)有所幫助。
原文鏈接:http://blog.csdn.net/m53931422/article/details/41788535