歸併排序
歸併排序是遞歸的分治算法
分治
分治的思想是把一個複雜的問題分成兩個或多個相同或相似的子問題,再把子問題分成更小的子問題直到最後子問題可以簡單地直接求解;
比如快排、歸併排序 傅里葉變換等
分治策略:對於一個規模爲n的問題,若該問題可以容易的解決(比如規模n較小)則直接解決,否則將其分解爲k個規模較小的子問題,這些子問題互相獨立且與原問題形式相同,遞歸地解決這些子問題,然後將各個子問題的解合併得到原問題的解。
複雜度
由於歸併排序每次劃分時兩個子序列的長度基本一樣,所以歸併排序最好、最差和平均時間複雜度都是nlog2n
歸併排序是一種穩定的排序方法,速度僅次於快排
代碼:
使用了單例模式,方便在程序內部比較不同算法的移動/比較次數,不需要的刪掉就可以
import javafx.scene.control.skin.SliderSkin;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class Merge_sort {
public static Merge_sort merge_sort;
private Merge_sort() {
}
private int com_step;
private int move_step;
public int getCom_step() {
return com_step;
}
public int getMove_step() {
return move_step;
}
public static Merge_sort getMerge_sort() {
if (merge_sort == null) {
synchronized (Insert_sort.class) {
if (merge_sort == null) {
merge_sort = new Merge_sort();
}
}
}
return merge_sort;
}
// private Integer[] change_to_nums(List<Integer> list){
// Integer[] nums=list.toArray(new Integer[0]);
// return nums;
// }
public List<Integer> in_order(List<Integer> list){
Integer[] nums=list.toArray(new Integer[0]);
list=in_order1(nums,0,nums.length-1);
return list;
}
private List<Integer> in_order1(Integer[] nums,int l,int r) {
com_step = 0;
move_step = 0;
// Integer[] nums = list.toArray(new Integer[0]);//將列表list轉爲Integer對象數組
com_step++;
if(l<r){//當子序列中只有一個元素時結束遞歸
int mid=(l+r)/2;
in_order1(nums,l,mid);//對左右子序列分別排序
in_order1(nums,mid+1,r);
mergsort(nums,l,mid,r);
}
return new ArrayList<>(Arrays.asList(nums));
}
private Integer[] mergsort(Integer[] nums,int l,int mid,int r){
// Integer[] tem=new Integer[nums.length];//輔助數組
int []tmp=new int[nums.length];//輔助數組
int p1=l,p2=mid+1,k=l;//p1、p2是檢測指針,k是存放指針
while(p1<=mid && p2<=r){//每次執行都把兩個子序列中最小的元素放入臨時數組(不能用||,否則可能出現一個序列中最大元素比另一個最小元素大的情況)
com_step+=3;
if(nums[p1]<=nums[p2])
tmp[k++] = nums[p1++];
else
tmp[k++]=nums[p2++];
move_step++;
}
while(p1<=mid) {//如果第一個序列未檢測完,直接將後面所有元素加到合併的序列中
com_step++;
move_step++;
tmp[k++]=nums[p1++];
}
while(p2<=r) {//同上
com_step++;
move_step++;
tmp[k++]=nums[p2++];
}
//複製回原數組
for (int i = l; i <=r; i++) {
move_step++;
nums[i] = tmp[i];
}
return nums;
}
}