Java 十大排序算法之歸并排序刨析
歸并排序原理
1.盡可能的一組數(shù)據(jù)拆分成兩個元素相等的子組,并對每一個子組繼續(xù)拆分,直到拆分后的每個子組的元素個數(shù)是1為止。
⒉將相鄰的兩個子組進行合并成一個有序的大組。
3.不斷的重復步驟2,直到最終只有一個組為止。
歸并排序API設計
| 類名 | Merge |
| 構(gòu)造方法 | Merge():創(chuàng)建Merge對象 |
| 成員方法 |
1.public static void sort(Comparable[] a):對數(shù)組內(nèi)的元素進行排序 2.private static void sort(Comparable[] a,int lo,int hi):對數(shù)組a中從索引lo到索引hi之間的元素進行排序 3.private static void merge(Comparable[] a,int lo,int mid,int hi):從索引lo到索引mid為一個子組,從索引mid+1到索引hi為另一個子組,把數(shù)組a中的這兩個子組的數(shù)據(jù)合并成一個有序的大組(從索引lo到索引hi) 4.private static boolean less(Comparable v,Comparable w):判斷v是否小于w 5.private static void exchange(Comparable[] a,int i,int j):交換a數(shù)組中,索引i和索引j處的值 |
| 成員變量 | private static ComParable[] assit:完成歸并操作需要的輔助數(shù)組 |
歸并排序代碼實現(xiàn)
public class Merge {
//輔助數(shù)組
private static Comparable[] assist;
//對數(shù)組a中的元素進行排序
public static void sort(Comparable[] a){
assist=new Comparable[a.length];
int lo=0;
int hi=a.length-1;
sort(a,lo,hi);
}
//對數(shù)組a中從lo到hi的元素進行排序
private static void sort(Comparable[] a,int lo,int hi){
if(hi<=lo){
return;
}
int mid=lo+(hi-lo)/2;
//對lo到mid之間的元素進行排序
sort(a,lo,mid);
//對mid+1到hi之間的元素進行排序
sort(a,mid+1,hi);
//對lo到mid這組數(shù)據(jù)和mid到hi這組數(shù)據(jù)進行歸并
merge(a,lo,mid,hi);
}
//對數(shù)組中,從lo到mid為一組,從mid+1到hi為一組,對這兩組數(shù)據(jù)進行歸并
public static void merge(Comparable[] a,int lo,int mid,int hi){
//lo到mid這組數(shù)據(jù)和mid+1到hi這組數(shù)據(jù)歸并到輔助數(shù)組assist對應的索引處
int i=lo;//定義一個指針,指向assist數(shù)組中開始填充數(shù)據(jù)的索引
int p1=lo;//定義一個指針,指向第一組數(shù)據(jù)的第一個元素
int p2=mid+1;//定義一個指針,指向第二組數(shù)據(jù)的第一個元素
//比較左邊小組和右邊小組中的元素大小,哪個小,就把哪個數(shù)據(jù)填充到assist數(shù)組中
while(p1<=mid&&p2<=hi){
if(less(a[p1],a[p2])){
assist[i++]=a[p1++];
}else{
assist[i++]=a[p2++];
}
}
//把未填充的數(shù)據(jù)填到assist中
while(p1<=mid){
assist[i++]=a[p1++];
}
while(p2<=hi){
assist[i++]=a[p2++];
}
for(int index=lo;index<=hi;index++){
a[index]=assist[index];
}
}
//比較v元素是否小于w元素
private static boolean less(Comparable v,Comparable w){
return v.compareTo(w)<0;
}
//數(shù)組元素i和j交換位置
private static void exchange(Comparable[] a,int i,int j){
Comparable t=a[i];
a[i]=a[j];
a[j]=t;
}
}
//測試代碼
class Test{
public static void main(String[] args) {
Integer[] a={8,4,6,5,7,1,3,6,2};
Merge.sort(a);
System.out.println(Arrays.toString(a));
}
}
歸并排序的時間復雜度分析
歸并排序是分治思想的最典型的例子,上面的算法中,對a[lo..hi]進行排序,先將它分為a[lo..mid]和a[mid+1..hi]兩部分,分別通過遞歸調(diào)用將他們單獨排序,最后將有序的子數(shù)組歸并為最終的排序結(jié)果。該遞歸的出口在于如果一個數(shù)組不能再被分為兩個子數(shù)組,那么就會執(zhí)行merge進行歸并,在歸并的時候判斷元素的大小進行排序。
用樹狀圖來描述歸并,如果一個數(shù)組有8個元素,那么它將每次除以2找最小的子數(shù)組,共拆log8次,值為3,所以樹共有3層那么自頂向下第k層有2^k個子數(shù)組,每個數(shù)組的長度為2^(3-k),歸并最多需要2^(3-k)次比較。因此每層的比較次數(shù)為2^k * 2^(3-k)=2^3,那么3層總共為3*2^3。
假設元素的個數(shù)為n,那么使用歸并排序拆分的次數(shù)為log2(n).所以共log2(n)層,那么使用log2(n)替換上面3*2^3中的3這個層數(shù),最終得出的歸并排序的時間復雜度為︰log2(n)*2^(log2(n))=log2(n)*n,根據(jù)大O推導法則,忽略底數(shù),最終歸并排序的時間復雜度為O(nlogn);
歸并排序的缺點∶
需要申請額外的數(shù)組空間,導致空間復雜度提升,是典型的以空間換時間的操作。
到此這篇關于Java 十大排序算法之歸并排序刨析的文章就介紹到這了,更多相關Java 歸并排序內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Springboot+Thymeleaf+Jpa實現(xiàn)登錄功能(附源碼)
最近有學習到關于Springboot+Thymeleaf+Jpa的綜合運用知識,因此想寫一個簡單的登錄界面來嘗試一下,需要的朋友們下面隨著小編來一起學習學習吧2021-05-05
關于spring中單例Bean引用原型Bean產(chǎn)生的問題及解決
這篇文章主要介紹了關于spring中單例Bean引用原型Bean產(chǎn)生的問題及解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-06-06
一篇文章帶你解決 IDEA 每次新建項目 maven home directory 總是改變的問題
這篇文章主要介紹了一篇文章帶你解決 IDEA 每次新建項目 maven home directory 總是改變的問題,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-09-09
Java中如何使用Gson將對象轉(zhuǎn)換為JSON字符串
這篇文章主要給大家介紹了關于Java中如何使用Gson將對象轉(zhuǎn)換為JSON字符串的相關資料,Gson是Google的一個開源項目,可以將Java對象轉(zhuǎn)換成JSON,也可能將JSON轉(zhuǎn)換成Java對象,需要的朋友可以參考下2023-11-11
深入理解Java責任鏈模式實現(xiàn)靈活的請求處理流程
本文詳細介紹了Java中的責任鏈模式,幫助您理解其工作原理,以及如何在代碼中實現(xiàn)。該模式可以將請求沿著處理鏈路傳遞,實現(xiàn)靈活的請求處理流程。通過本文的學習,您將獲得在Java應用程序中使用責任鏈模式的知識和技能2023-04-04

