归并排序的思想:
归并排序(MERGE-SORT)是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。归并排序是一种稳定的排序方法。
归并排序图解
下面是上图最后一次合并的图解
要将{4,5,7,8}和{1,2,3,6}合并成最后的顺序{1,2,3,4,5,6,7,8}
根据图解我们不难理解,归并排序其实就是把一个序列先分解,再合并的排序算法。
下面代码实现:
首先先写一个合并的方法:
/**
*
* @param arr 排序的原始数组
* @param left 左边有序序列的初始索引
* @param mid 中间索引
* @param right 右边索引
* @param temp 做中转的数组
*/
public static void merge(int arr[], int left, int mid, int right, int temp[]) {
int l = left;// 左边有序序列的初始指针
int r = mid + 1;// 右边有序序列的初始指针
int Index = 0;// 中转的数组的初始指针
// (第一步)
// 先把左右两边(有序)的数据按照规则填充到temp数组
// 直到左右两边的有序序列,有一边处理完毕为止
while (l <= mid && r <= right) {
if (arr[l] <= arr[r]) {// 左边的有序序列的当前元素,小于等于右边有序序列的当前元素
temp[Index++] = arr[l++];// 将左边有序序列的当前元素,填充到temp数组
} else if (arr[r] <= arr[l]) {// 右边的有序序列的当前元素,小于等于左边有序序列的当前元素
temp[Index++] = arr[r++];// 反之,将右边有序序列的当前元素,填充到temp数组
}
}
// (第二步)
// 把有剩余数据的一边的数据依次全部填充到temp
while (l <= mid) {
temp[Index++] = arr[l++];
}
while (r <= right) {
temp[Index++] = arr[r++];
}
// (第三步)
// 将temp数组的元素拷贝到arr
Index = 0;
int templeft = left;
while (templeft <= right) {
arr[templeft++] = temp[Index++];
}
}
需要注意第三步的拷贝并不是每次都像最后一次合并的图解那样有8个数
tempLeft = 0 , right=3 / / tempLeft=4 , right = 7
当第一次合并时,只有4个数
tempLeft = 0 , right = 1 / / tempLeft = 2 , right = 3
然后写一个递归分解结合合并的方法:
public static void mergeSort(int[] arr, int left, int right, int[] temp) {
if (left < right) {
int mid = (right + left) / 2;
// 分解
mergeSort(arr, left, mid, temp);// 向左递归
mergeSort(arr, mid + 1, right, temp);// 向右递归
// 合并
merge(arr, left, mid, right, temp);
}
}
归并排序的算法就写完了~
下面老规矩,还是用10w个数测试一下排序的速度:
public static void main(String[] args) {
// TODO 自动生成的方法存根
// int arr[] = { 8, 4, 5, 7, 1, 3, 6, 2 };
int arr[] = new int [100000];
int temp[] = new int[arr.length];
for(int i=0;i<arr.length;i++) {
arr[i] = (int)(Math.random() * 8000);
}
Date data1 = new Date();
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String date1Str = simpleDateFormat.format(data1);
System.out.println("排序前的时间是 " + date1Str);
//测试归并排序
mergeSort(arr, 0, arr.length - 1, temp);
Date data2 = new Date();
String date2Str = simpleDateFormat.format(data2);
System.out.println("排序后的时间是=" + date2Str);
// System.out.println(Arrays.toString(arr));
}
秒排~
再试试100w的数据:
还是秒排~