package sort;/** * 归并排序相比较之前的排序算法而言加入了分治法的思想,其算法思路如下: * * 1.如果给的数组只有一个元素的话,直接返回(也就是递归到最底层的一个情况) * * 2.把整个数组分为尽可能相等的两个部分(分) * * 3.对于两个被分开的两个部分进行整个归并排序(治) * * 4.把两个被分开且排好序的数组拼接在一起 */public class Merge<T extends Comparable<T>> { public void mergeArr(T[] arr, int l, int mid, int r){ T[] aux = (T[])(new Object[r - l + 1]); for(int i = l; i <= r; i++) aux[i - l] = arr[i]; //双指针操作 int i = l, j = mid + 1; for(int k = l; k <= r; k++){ if(i > mid){ arr[k] = aux[j - l]; j++; }else if(j > r){ arr[k] = aux[i - l]; i++; }else if(aux[i-l].compareTo(aux[j - l]) < 0){ arr[k] = aux[i - l]; i ++; }else{ arr[k] = aux[j - l]; j ++; } } } //递归使用递归排序, 对arr[l...r]的范围进行排序 public void merge(T[] arr, int l, int r){// if( l >= r)// return; if(r - l <= 15){ insertionSort(arr, l, r); return; } int mid = (l + r) / 2; merge(arr, l, mid); merge(arr, mid + 1, r); if(arr[mid].compareTo(arr[mid + 1]) > 0) mergeArr(arr, l, mid, r); } private void insertionSort(T[] arr, int l, int r) { for(int i = l + 1; i <= r; i++){ T t = arr[i]; int j; //依次循环将数据后移一个位置, 最后在插入 for(j = i; j > l && arr[j - 1].compareTo(t) > 0; j--) arr[j] = arr[j - 1]; arr[j - 1] = t; } return; } public void mergeSort(T[] arr, int n){ merge(arr, 0, n - 1); } /** * 以下是经典的归并排序算法 * @param arr 数组 * @param l 左边界 * @param r 右边界 */ void mergeSort(int[] arr, int l, int r) { if (l < r) { int m = l+(r-l)/2; mergeSort(arr, l, m); mergeSort(arr, m+1, r); merge(arr, l, m, r); } } private void merge(int[] arr, int l, int m, int r) { int i, j, k; int n1 = m - l + 1; int n2 = r - m; int[] L = new int[n1]; int[] R = new int[n2]; /* 拷贝新数组 */ for (i = 0; i < n1; i++) L[i] = arr[l + i]; for (j = 0; j < n2; j++) R[j] = arr[m + 1+ j]; i = 0; j = 0; k = l; /* * 对两个数组在不越界的情况下,分别拷贝数组直到一个数组越界 */ while (i < n1 && j < n2) { if (L[i] <= R[j]) { arr[k] = L[i]; i++; }else { arr[k] = R[j]; j++; } k++; } /* 将不越界的数组拷贝到新数组中 */ while (i < n1) { arr[k] = L[i]; i++; k++; } while (j < n2) { arr[k] = R[j]; j++; k++; } }}