基本介绍
递归加合并,先分解后合并。
——爱因斯坦
核心思想
归并排序(MERGE-SORT)是利用归并的思想实现的排序方法,该算法采用经典的分治(divide-and-conquer)策略(分治法将问题分(divide)成一些小的问题然后递归求解,而治(conquer)的阶段则将分的阶段得到的各答案"修补"在一起,即分而治之)。
实例讲解
主要思路
- 当左侧下标小于右侧下标时,求得中间位置索引,然后向其左右两侧递归排序,最终将排序的结果合并到一起。
- 重点是两个有序的子序列合并到一个有序序列:定义临时数组用于存放合并后的有序序列,然后将临时数组的结果赋值回原来的数组中。具体为定义三个指针分别指向子序列1,子序列2,临时数组,然后同时相同访问两个子序列,每次两两比较将值小的那个放入到临时数组中,然后指针往后移动,继续两个序列中的对应值两两比较,直到某一个子序列的元素全部放入到了临时数组中为止,此时将另一个有序子序列的其他元素放入到临时数组即可,最终将临时数组的所有元素拷贝回原数组即可。
- 结合代码,更易消化。
图示演示
动图演示
总体思路图示
子序列合并过程图示
代码实现
Talk is cheap, show me the code.
import java.io.*;
import java.util.*;
// Author:Peiliang Gong
// MergeSort.
class Sort
{
//main function
public static void main (String[] args) throws java.lang.Exception
{
int[] arr = {3,-1,56,0,0,0,7,-3,2,-4};
int[] temp = new int[arr.length];
mergeSort(arr, 0, arr.length-1,temp);
System.out.println("排序后的结果为:"+Arrays.toString(arr));
}
private static void mergeSort(int[] arr, int left, int right, int[] temp) {
if(left < right){
int mid = (left + right) / 2;
//递归处理
mergeSort(arr, left, mid, temp);
mergeSort(arr, mid+1, right, temp);
//合并已排序结果
merge(arr, left, mid, right, temp);
}
}
private static void merge(int[] arr, int left, int mid, int right, int[] temp){
// i指向左边有序序列起始位置,j指向右边有序序列起始位置,t索引临时数组的位置
int i = left;
int j = mid+1;
int t = 0;
//依次扫描两个有序序列,将小的一个加入到临时数组内
while(i <= mid && j <= right){
if(arr[i] <= arr[j]){
temp[t] = arr[i];
i++;
}else{
temp[t] = arr[j];
j++;
}
t++;
}
//将有序数组中剩余的元素加入到临时数组中
while(i <= mid){
temp[t] = arr[i];
i++;
t++;
}
while(j <= right){
temp[t] = arr[j];
j++;
t++;
}
//将临时数组的元素重新赋值给原始数组,注意每次不是将所有的数都赋值回去,是将当前排序好的结果赋值回原来数组对应位置
int tempLeft = left;
t = 0;
while(tempLeft <= right){
arr[tempLeft] = temp[t];
tempLeft++;
t++;
}
}
}