归并排序采用分治法的思想:将原问题分解为若干规模较小但类似于原问题的子问题,递归地求解这些子问题,再合并这些子问题的解来建立原问题的解。
分治模式在每层递归时都有三个步骤:
分解原问题为若干子问题,它们是原问题的规模较小的实例。
解决这些子问题,递归地求解各子问题,若子问题足够小,则直接求解
合并这些子问题的解成原问题的解
归并排序算法遵循分治模式:
分解:分解待排序的n个元素的序列成各具n/2个元素的两个子序列。
解决:使用归并排序递归地排序两个子序列。
合并:合并两个已排序的子序列生产已排序的答案。
代码如下:
import java.util.Arrays;
public class MergeSort{
public static void main(String[] args){
int a[] = {42, 14, 52, 40, 28, 74, 48, 9, 22, 35, 61};
mergeSort(a, 0, a.length - 1);
System.out.println(Arrays.toString(a));
}
public static void mergeSort(int a[], int begin, int end){
if(begin >= end)
return;
//使用递归完成排序
int mid = (begin + end) >> 1; //除以2
mergeSort(a, begin, mid);
mergeSort(a, mid + 1, end);
merge(a, begin, mid, end);
}
//归并两路有序序列
public static void merge(int a[], int begin, int mid, int end){
int arr[] = new int[end + 1]; //临时数组保存排好序的数,使用[begin,end]区间
int low = begin; //临时数组的下标
int left = begin; //保存数组起始左下标
int center = mid + 1; //右路序列起始下标,左路为begin
//将数组中小的保存到临时数组,若要降序把 > 换成 <
while(begin <= mid && center <= end){
arr[low++] = a[begin] > a[center] ? a[center++] : a[begin++];
}
//将上面while循环未移动的数字移入临时数组
while(begin <= mid){
arr[low++] = a[begin++];
}
while(center <= end){
arr[low++] = a[center++];
}
//将临时数组中的数字保存到数组a
for(int i = left; i <= end; i++){
a[i] = arr[i];
}
}
}
输出:
[9, 14, 22, 28, 35, 40, 42, 48, 52, 61, 74]