归并排序算法是基于归并(Merge)操作的一种有效排序算法,是采用分治法(Divide and Conquer)的典型应用。归并排序算法将待排序序列分为若干个子序列,先对每个子序列进行排序,等每个子序列都有序后,再将有序子序列合并为整体的有序序列。若将两个有序表合并成一个有序表,则称之为二路归并。
归并排序的原理是先将原始数组分解为多个子序列,然后对每个子序列进行排序,最后将排好序的子序列合并起来。如图5-8所示为对数组[4,1,3,9,6,8]进行归并排序,先经过两次分解,将数组分解成4个子序列,然后对子序列数组进行排序和归并,最终得到排好序的数组[1,3,4,6,8,9]。
归并排序算法的Java实现如下:
public static int[] mergeSort(int[] data) {
sort(data, 0, data.length - 1);
return data;
}
//对左右两边的数据进行递归
public static void sort(int[] data, int left, int right) {
if (left >= right)
return;
//找出中间索引
int center = (left + right) / 2;
//对左边的数组进行递归
sort(data, left, center);
//对右边的数组进行递归
sort(data, center + 1, right);
//将两个数组进行归并
merge(data, left, center, right);
}
/**
* 将两个数组进行归并:两个数组在归并前是有序数组,在归并后依然是有序数组
* @param data:数组对象;left:左边数组第1个元素的索引;
* center左边数组最后一个元素的索引,center+1是右边数组第1个元素的索引
* right:右边数组最后一个元素的索引
*/
public static void merge(int[] data, int left, int center, int right) {
//临时数组
int[] tmpArr = new int[data.length];
//右边数组第1个元素的索引
int mid = center + 1;
//third记录临时数组的索引
int third = left;
//缓存左边数组第1个元素的索引
int tmp = left;
while (left <= center && mid <= right) {
//从两个数组中取出最小的值放入临时数组中
if (data[left] <= data[mid]) {
tmpArr[third++] = data[left++];
} else {
tmpArr[third++] = data[mid++];
}
}
//将剩余部分依次放入临时数组(实际上两个while只会执行其中一个)中
while (mid <= right) {
tmpArr[third++] = data[mid++];
}
while (left <= center) {
tmpArr[third++] = data[left++];
}
//将临时数组中的内容复制到原数组中
//(原left-right范围内的内容被复制到原数组中)
while (tmp <= right) {
data[tmp] = tmpArr[tmp++];
}
}
以上代码定了3个方法:mergeSort()是归并排序方法的入口;sort()对数据进行递归拆解和合并;merge()进行数据排序和合并。其中,sort()每次都将数组进行二分拆解,然后对左侧的数组和右侧的数据分别进行递归。merge()先将数组进行冒泡排序,然后依次将冒泡排序的结果放入临时数组中,最后将排好序的临时数组放入排序数组中。