歸併排序是乙個相當快速的演算法,其時間複雜度穩定在o(n*logn),在面試中被問到的頻率也挺高的,今天就來介紹一下這個排序演算法
手撕面試題演算法<排序>(1)—— 氣泡排序及其優化實現
手撕面試題演算法<排序>(2)—— 選擇排序
手撕面試題演算法<排序>(3)—— 插入排序及其優化實現
手撕面試題演算法<排序>(3.5)—— 希爾排序
手撕面試題演算法<排序>(4)—— 歸併排序
手撕面試題演算法<排序>(5)—— 快速排序以及快排為什麼快
手撕面試題演算法<排序>(6)—— 堆 & 堆排序
手撕面試題演算法<排序>(7)—— 箱排序 & 基數排序
看完有收穫別忘了點個star哦~ 測試
在歸併排序中體現的是分治的思想,其將乙個陣列一分為二,二分為四,直到不能再分——將難以處理的大問題拆分成容易處理的小問題,最後再將排序完畢的陣列合併在一起,完成陣列的排序
將乙個陣列對半拆分處理的時間複雜度是o(logn)
例,對乙個長度為n的陣列進行遞迴拆分:
而每次對子區間的排序的次數為:
所以歸併排序總共需要走logn次o(n)的操作,的時間複雜度為 o(n*logn)
我們使用遞迴來將陣列進行拆分
通過傳入的陣列,以及區間[l, r],來對半劃分陣列,並將劃分後的l, r記錄下來進行下一次遞迴,直到l >= r
陣列的歸併就是將兩條陣列重排序後合併成一條陣列的過程private
static
void
sort
(int
arr,
int l,
int r)
}
這個過程跟手撕面試題演算法<鍊錶> (1)——鍊錶合併系列非常類似,可以參考一下private
static
void
merge
(int
arr,
int l,
int mid,
int r)
while
(i <= mid) tmparr[idx++
]= arr[i++];
while
(j <= r) tmparr[idx++
]= arr[j++];
// 將tmparr陣列中排序完畢的值放回原陣列中
for(
int val : tmparr)
}
上面的sort遞迴方法需要傳入l和r,對使用者來說不太友好,我們可以過載乙個只需要傳入陣列的sort入口方法:
排序測試:public
static
void
sort
(int
arr)
百萬級陣列測試:
int n =
1_000_000;
int[
] arr = tester.
randomarr
(n);
system.out.
println
("對有"
+ n +
"個元素的隨機數組進行排序:");
long start = system.
currenttimemillis()
;sort
(arr)
;long end = system.
currenttimemillis()
; system.out.
println
("歸併排序結束,耗時"
排序演算法(4) 歸併排序
簡介 歸併排序是建立在歸併操作上的一種有效的排序演算法,該演算法是採用分治法 divide and conquer 的乙個非常典型的應用。將已有序的子串行合併,得到完全有序的序列 即先使每個子串行有序,再使子串行段間有序。若將兩個有序表合併成乙個有序表,稱為二路歸併。一 主要步驟 將待排序陣列 0....
手撕演算法 排序
時間複雜度o n 2 o n 2 o n2 空間複雜度 o 1 穩定 從第乙個元素開始,認為左邊的序列是有序的,從有序部分的最後乙個向前比較,如果當前元素小於有序部分就交換,否則比較下乙個元素。function insertmerge arr else return arr let arr 1 5,...
4 歸併排序演算法
1 歸併排序 merge sort 基本思想 歸併排序法是將兩個或兩個以上的有序表合併成乙個新的有序表 即將待排序的序列分成若干個子串行,每個子串行是有序的,然後再把有序子串行合併為整體子串行 利用歸併的思想實現二路歸併排序的實現步驟 首先將整個資料表看成是n個有序子表,每個子表長度為1 當然有序啦...