归并排序
归并排序是递归的分治算法
分治
分治的思想是把一个复杂的问题分成两个或多个相同或相似的子问题,再把子问题分成更小的子问题直到最后子问题可以简单地直接求解;
比如快排、归并排序 傅里叶变换等
分治策略:对于一个规模为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;
}
}