归并排序
参考文章:https://zhuanlan.zhihu.com/p/36075856
核心思想图解:
排序步骤:
先把左右两边(有序)的数据按照规则填充到temp数组,直到左右两边的有序序列,有一边处理完毕为止
- 如果左边的有序序列的当前元素,小于等于右边有序序列的当前元素即将左边的当前元素,填充到 temp数组,然后 t++, i++
- 反之,将右边有序序列的当前元素,填充到temp数组
把剩余的有序序列依次填充到临时temp数组
- 左边剩余填充到temp
- 或右边剩余填充到temp
将排序好的temp填充到原来的array中
代码实现
package com.lilvencent.sort;
import java.util.Arrays;
/**
* @author Lil
* @date 2020/12/5 16:51
*/
public class Merget02 {
public static void main(String[] args) {
int arry[] = {8,4,5,7,1,3,6,2};
int temp[] = new int[arry.length];
mergeSort(arry,0,arry.length-1,temp);
System.out.println("归并排序后=" + Arrays.toString(arry));
}
// 归并
private static void mergeSort(int array[], int first, int last, int temp[]) {
if (first < last) {
int mid = (first + last) / 2;
mergeSort(array, first, mid, temp); // 递归归并左边元素
mergeSort(array, mid + 1, last, temp); // 递归归并右边元素
mergeArray(array, first, mid, last, temp); // 再将二个有序数列合并
}
}
private static void mergeArray(int array[], int first, int mid, int last, int temp[]) {
int i = first, j = mid + 1; // i为第一组的起点, j为第二组的起点
int m = mid, n = last; // m为第一组的终点, n为第二组的终点
int k = 0; // k用于指向temp数组当前放到哪个位置
//(一)
//先把左右两边(有序)的数据按照规则填充到temp数组
//直到左右两边的有序序列,有一边处理完毕为止
while (i <= m && j <= n) { // 将两个有序序列循环比较, 填入数组temp
if (array[i] <= array[j])
temp[k++] = array[i++];
else
temp[k++] = array[j++];
}
//(二)
//把有剩余数据的一边的数据依次全部填充到temp
while (i <= m) { // 如果比较完毕, 第一组还有数剩下, 则全部填入temp
temp[k++] = array[i++];
}
while (j <= n) {// 如果比较完毕, 第二组还有数剩下, 则全部填入temp
temp[k++] = array[j++];
}
//(三)
//将temp数组的元素拷贝到arr
//注意,并不是每次都拷贝所有
for (i = 0; i < k; i++) {// 将排好序的数填回到array数组的对应位置
array[first + i] = temp[i];
}
}
}
总结
在临时数组完成小部分排序的时候,将其复制到原来数组的时候需要理解其中的参数,比较难理解。还有利用递归将数组分开数组需要理解一下。