算法基础:2. 归并排序
归并排序法
分而治之
// 伪代码
MergeSort(arr, l, r) {
if (l >= r) return ; // 求解最基本问题
int mid = (l + r) / 2;
// 对arr[l , mid] 排序
MergeSort(arr, l, mid);
// 对arr[mid+1, r] 排序
MergeSort(arr, mid+1, r);
// 将arr[l, mid] 和 arr[mid+1, r]合并
merge(arr, l, mid, r);
}
归并过程
已知两个有序数组A、B,将A、B合并成一个新的有序数组?
method1:A,B本身有序,所以只要看当前两个数组中哪个元素最小,则就是合并后数组的最小元素。依次类推。
method2:备份原数组,覆盖
public class MergeSort<E> {
public MergeSort() {}
public static <E extends Comparable<E>> void sort(E[] arr) {
mergeSort(arr, 0 , arr.length - 1);
}
private static <E extends Comparable<E>> void mergeSort(E[] arr, int l, int r) {
if (l >= r) return ;
int mid = l + (r - l) / 2;
mergeSort(arr, l, mid);
mergeSort(arr, mid+1, r);
merge(arr, l, mid, r);
}
// 合并两个有序区间arr[l, mid], arr[mid+1, r]
public static <E extends Comparable<E>> void merge(E[] arr, int l, int mid, int r) {
E[] tmp = Arrays.copyOfRange(arr, l, r + 1);
int i = l, j = mid + 1;
// 每轮循环为arr[k] 赋值
for (int k = l; k <= r; k++) {
// 如果i,j越界
if (i > mid) {
arr[k] = tmp[j - l]; // 减去偏移: tmp数组从0开始的,而arr数组从l开始的
j++;
} else if (j > r) {
arr[k] = tmp[i - l];
i++;
} else if (tmp[i - l].compareTo(tmp[j - l]) <= 0) {
arr[k] = tmp[i - l];
i++;
} else {
arr[k] = tmp[j - l];
j++;
}
}
}
}
优化
// 优化1: 如果mid的元素已经小于等于mid+1的元素
//(即前一个有序数组的最后一个元素已经小于等于后一个有序数组的第一个元素,意味着区间l到r已经有序)
if (arr[mid].comparaTo(arr[mid+1]) > 0)
merge(arr, l, mid, r);
// 优化2:对小规模数据使用插入排序
private static <E extends Comparable<E>> void mergeSort2(E[] arr, int l, int r) {
if (r - l <= 15) { // 15随意取的
InsertSort.sort2(arr, l, r); // 插入排序
return;
}
int mid = l + (r - l) / 2;
mergeSort2(arr, l, mid);
mergeSort2(arr, mid+1, r);
// 优化1:如果数组本身有序,则不需要进行merge操作
if (arr[mid].compareTo(arr[mid+1]) > 0)
merge(arr, l, mid, r);
}
本文来自博客园,作者:micromatrix,转载请注明原文链接:https://www.cnblogs.com/cenjw/p/ds-merge-sort.html
posted on 2022-05-01 10:27 micromatrix 阅读(42) 评论(0) 编辑 收藏 举报