归并排序
原理(分治的思想)
过程
1.递归分治
2.最后通过merge合并(具体操作过程)
- 定义3个变量 , “ L “
代表头部, “ mid “代表中间位置(L+R)/2, “ r “代表最后的位置, “ arr “为要排序的数组 - 先复制一个相同的数组,被复制的那个数组比原数组多1
每轮为 arr[k] 赋值
- 前半段已经排完的情况
- 后半段已经排完的情况
- 排序的两个数前大后小
-
3. 代码部分
```java public class MergeSort {
private MergeSort(){ }
public static
> void sort(E[] arr){ sort(arr,0,arr.length-1); } private static > void sort(E[] arr,int l,int r){ if (l >= r) return; int mid = (l+r) / 2; sort(arr,l,mid); sort(arr,mid+1,r); merge(arr,l,mid,r); }
//合并两个有序区间 arr[l,mid] arr[mid+1,r]private static <E extends Comparable<E>> void merge(E[] arr,int l,int mid,int r){//1.先复制一个相同的数组,被复制的那个数组比原数组多1E[] temp = Arrays.copyOfRange(arr,l,r+1);//前半个从l开始,后半个从mid+1开始int i = l, j = mid+1;//2.每轮为 arr[k] 赋值for (int k = l; k <= r; k++) {if (i>mid){//前半段已经排完了,可以直接把后半段的赋值给temp// 因为temp从0开始,而arr从l开始,因此赋值应该从j-l开始arr[k] = temp[j-l]; j++;}else if (j>r){//后半段已经排完了,直接把前半段的赋值给temparr[k] = temp[i-l]; i++;}else if (temp[i-l].compareTo(temp[j-l]) <= 0){arr[k] = temp[i-l];i++;}else {arr[k] = temp[j-l];j++;}}}
}
<a name="vIoPP"></a>## 微观上的过程<a name="AarAi"></a>## 复杂性<a name="H1Guy"></a># 归并排序优化<a name="QgReW"></a>## 1.先判断再merge```javaif(arr[mid].compareTo(arr[mid+1])>0)merge(arr,l,mid,r,temp);
- 如果队列已经有序了就不必要再排队了
2.在一定的区间内使用插入排序法(有时候会翻车)
if (r-l <= 15){InsertionSort.sort2(arr,l,r);return;}
自底向上的归并排序算法
总结
- 首先是一个递归算法
- 是一个典型的分治算法
- 时间复杂度:O(nlogn)
- 加入对merge的优化后,对基本有序的数组,O(n)的
- 优化
- 判断是否需要merge
- 对小规模数据使用插入排序
- 只创建一个临时空间
- 归并排序不是原地排序算法
- 还可以实现自底向上
- 可以用来求解逆序对数问题
