Java分治歸并排序算法實(shí)例詳解
本文實(shí)例講述了Java分治歸并排序算法。分享給大家供大家參考,具體如下:
1、分治法
許多有用的算法在結(jié)構(gòu)上是遞歸的:為了解決一個(gè)給定的問(wèn)題,算法一次或多次遞歸地調(diào)用其自身以解決緊密相關(guān)的若干子問(wèn)題。這些算法典型地遵循分治法的思想:將原問(wèn)題分解為幾個(gè)規(guī)模較小但類似于原問(wèn)題的子問(wèn)題,遞歸地求解這些子問(wèn)題,然后再合并這些子問(wèn)題的解來(lái)建立原問(wèn)題的解。
分治模式在每層遞歸時(shí)都有三個(gè)步驟:
(1)分解原問(wèn)題為若干子問(wèn)題,這些子問(wèn)題是原問(wèn)題的規(guī)模較小的實(shí)例。
(2)解決這些子問(wèn)題,遞歸地求解各子問(wèn)題。然而,若子問(wèn)題的規(guī)模足夠小,則直接求解。
(3)合并這些子問(wèn)題的解成原問(wèn)題的解。
2、歸并排序算法
歸并排序算法完全遵循分治模式。直觀上其操作如下:
(1)分解:分解待排序的n個(gè)元素的序列成各具n/2個(gè)元素的兩個(gè)子序列。
(2)解決:使用歸并排序遞歸地排序兩個(gè)子序列。
(3)合并:合并兩個(gè)已排序的子序列以產(chǎn)生已排序的答案。
當(dāng)待排序的序列長(zhǎng)度為1時(shí),遞歸“開始回升”,在這種情況下不要做任何工作,因?yàn)殚L(zhǎng)度為1的每個(gè)序列都已排好序。歸并排序算法的關(guān)鍵操作是“合并”步驟中兩個(gè)已排序序列的合并。我們通過(guò)調(diào)用一個(gè)輔助過(guò)程Merge(A,p,q,r)來(lái)完成合并,其中A是一個(gè)數(shù)組,p、q和r是數(shù)組下標(biāo),滿足p<=q<r。該過(guò)程假設(shè)子數(shù)組A[p,q]和A[q+1,r]都已排好序。它合并這兩個(gè)子數(shù)組形成單一的已排好序的子數(shù)組并代替當(dāng)前的子數(shù)組A[p,r]。
過(guò)程Merge按以下方式工作?;氐轿覀兺鎿淇伺频睦?,假設(shè)桌上有兩堆牌面朝上的牌,每堆都已排序,最小的牌在頂上。我們希望把這兩堆牌合并成單一的排好序的輸出堆,牌面朝下地放在桌上。我們的基本步驟包括在牌面朝上的兩堆牌的頂上兩張牌中選取較小的一張,將該牌從其堆中移開(該堆的頂上將顯露一張新牌)并牌面朝下地將該牌放置到輸出堆。
下面是Merge的偽代碼:
Merge(A,p,q,r):
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)在我們可以把過(guò)程Merge作為歸并排序算法中的一個(gè)子程序來(lái)用。下面的過(guò)程Merge_sort(A,p,r)排序子數(shù)組A[p,r]中的元素。若p>=r,則該子數(shù)組最多有一個(gè)元素,所以已經(jīng)排好序。否則,分解步驟簡(jiǎn)單地計(jì)算一個(gè)下標(biāo)q,將A[p,r]分成兩個(gè)子數(shù)組A[p,q]和A[q+1,r],前者包含[n/2]個(gè)元素,后者包含[n/2]個(gè)元素。
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自底向上地說(shuō)明了當(dāng)n為2的冪時(shí)該過(guò)程的操作。算法由以下操作組成:合并只含1項(xiàng)的序列對(duì)形成長(zhǎng)度為2的排好序的序列,合并長(zhǎng)度為2的序列對(duì)形成長(zhǎng)度為4的排好序的序列,依此下去,直到長(zhǎng)度為n/2的兩個(gè)序列被合并最終形成長(zhǎng)度為n的排好序的序列。
3、Java代碼實(shí)現(xiàn)
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ù)組,長(zhǎng)度為要?dú)w并數(shù)組的長(zhǎng)度 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] + " "); } } }
PS:這里再為大家推薦一款關(guān)于排序的演示工具供大家參考:
在線動(dòng)畫演示插入/選擇/冒泡/歸并/希爾/快速排序算法過(guò)程工具:
http://tools.jb51.net/aideddesign/paixu_ys
更多關(guān)于java算法相關(guān)內(nèi)容感興趣的讀者可查看本站專題:《Java數(shù)據(jù)結(jié)構(gòu)與算法教程》、《Java操作DOM節(jié)點(diǎn)技巧總結(jié)》、《Java文件與目錄操作技巧匯總》和《Java緩存操作技巧匯總》
希望本文所述對(duì)大家java程序設(shè)計(jì)有所幫助。
相關(guān)文章
TensorFlow2中提供的幾種處理特征列的方法小結(jié)
本文主要介紹了TensorFlow2中提供的幾種處理特征列的方法小結(jié),主要介紹了6種方式,具有一定的參考價(jià)值,感興趣的可以了解一下2023-09-09macOS M1(AppleSilicon) 安裝TensorFlow環(huán)境
蘋果為M1芯片的Mac提供了TensorFlow的支持,本文主要介紹了如何給使用M1芯片的macOS安裝TensorFlow的環(huán)境,感興趣的可以了解一下2021-08-08python接口自動(dòng)化之使用token傳入到header消息頭中
這篇文章主要介紹了python接口自動(dòng)化之使用token傳入到header消息頭中問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-08-08利用python的socket發(fā)送http(s)請(qǐng)求方法示例
這篇文章主要給大家介紹了關(guān)于利用python的socket發(fā)送http(s)請(qǐng)求的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用python具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起看看吧2018-05-05Python數(shù)據(jù)可視化之用Matplotlib繪制常用圖形
Matplotlib能夠繪制折線圖、散點(diǎn)圖、柱狀圖、直方圖、餅圖. 我們需要知道不同的統(tǒng)計(jì)圖的意義,以此來(lái)決定選擇哪種統(tǒng)計(jì)圖來(lái)呈現(xiàn)我們的數(shù)據(jù),今天就帶大家詳細(xì)了解如何繪制這些常用圖形,需要的朋友可以參考下2021-06-06Python分支結(jié)構(gòu)(switch)操作簡(jiǎn)介
這篇文章主要介紹了Python分支結(jié)構(gòu)(switch)操作簡(jiǎn)介,具有一定借鑒價(jià)值,需要的朋友可以參考下2018-01-013行Python代碼實(shí)現(xiàn)圖像照片摳圖和換底色的方法
這篇文章主要介紹了3行Python代碼實(shí)現(xiàn)圖像照片摳圖和換底色的方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-10-10