归并排序原理解析及实现
一 归并排序原理
归并排序(MERGE-SORT)原理其实很简单,就是将大的无序序列分为若干个小的数组,然后利用 归并 的思想来实现的排序方法,其实就是经典的 分治 策略。
分:将大的序列不断分成小的序列进行排序求解
治:将分后所得的各个答案“合”在一起。
从图上看可以看到这种结构很像上下两棵满二叉树套在一起。
分阶段: 将序列通过递归拆分成子序列, 递归深度为logn。 就是图中上侧的满二叉树。
治阶段:将两两已经有序的子序列合并成一个有序序列,最终得到有序的大序列。就是图中下侧的满二叉树。用到的算法都是合并两个有序数组。
下图是遍历时处理元素的过程:
二 归并排序代码实现
完整的代码实现及解析如下:
public class MergeSort {
public static void mergeSort(int[] array, int start, int end, int temp[]){
if(start >= end){
return; // 当小序列不可再分时则返回
}
// 通过递归不断将数组拆分成两个,最后再进行排序并将排序后的结果合并返回
mergeSort(array, start, (start+end)/2, temp); // 递归拆出左半部分
mergeSort(array, (start+end)/2 + 1, end, temp); // 递归拆出右半部分
merge(array, start , end, temp); // 将两个拆分后的结果(有序数组)合并成新的有序数组
}
// 将两个小的有序序列排序合并成大的有序序列
public static void merge(int[] array, int start, int end, int[] temp){
// 通过以下三个索引将左右两部分有序序列合并成整体的有序序列
int mid = (start + end) / 2; // 所需合并大序列的中间索引
int left = start; // 左半部分的其实索引
int right = mid + 1; // 右半部分的其实索引
int index = left; // 临时数组temp的索引指针
// 通过双指针将左右两部分进行排序
while(left <= mid && right <= end){
if(array[left] < array[right]) temp[index++] = array[left++];
else temp[index++] = array[right++];
}
// 若另一半还有剩余部分则直接将剩余部分填充到后面
while(left <= mid) {temp[index++] = array[left++];}
while(right <= end) {temp[index++] = array[right++];}
// 将临时序列赋给原序列
for(int i = start; i <= end; i++){
array[i] = temp[i];
}
}
// 测试方法
public static void main(String[] args){
int[] arr = {6, 2, 3, 4, 8, 7, 1, 5};
int[] temp = new int[arr.length];
mergeSort(arr, 0, arr.length - 1, temp);
System.out.println(Arrays.toString(arr));
}
}