归并排序的思想是把一个数组分成两半,排序每一半,然后用Merge()方法把数组的两半归并成一个有序数组。如何来为每一部分排序呢?把每一部分都分成两个四分之一,对每个四分之一部分排序,然后把他们归并成为一个有序数组的一半。
类似的,每一对八分之一部分归并成为四分之一部分,每一对十六分之一归并成为八分之一部分,以此类推。反复的分割数组,知道得到了子数组只有一个数据项。这就是基值条件;设定只有一个数据项的数组是有序的。
在mergeSort()方法中,每一次这个方法调用自身的时候,排列都会被分为两个部分,并且方法每一次返回的时候都会把两个较小的排列合并成一个更大的排列。
当mergeSort()方法发现两个只有一个数据项的数组的时候,它就返回,把这两个数据项归并到一个有两个数据项的有序数组中。每个生成的一对有两个数据项的排列又被合并成一个有4个数据项的有序数组。这个过程一直持续下去,数组越来越大知道整个数组有序。当初始数组的数据项的个数是二的乘方的时候,是最容易看明白的。
代码:
package cnic.cn.impl;
public class MergeSort {
public static void main(String[] args) {
int[] array = new int[10];
array[0] = 10;
array[1] = 4;
array[2] = 6;
array[3] = 2;
array[4] = 15;
array[5] = 14;
array[6] = 56;
array[7] = 27;
array[8] = 16;
array[9] = 23;
mergeSort(array, 0,9);
for (int i = 0; i <= 9; i++) {
System.out.println(array[i]);
}
}
private static void mergeSort(int[] v,int lowerBound,int upperBound){
if(lowerBound==upperBound){
System.out.println("first:"+lowerBound+"---------"+"last"+upperBound);
System.out.println(v[lowerBound]);
return;
}else{
int mid= (lowerBound+upperBound)/2;
mergeSort(v, lowerBound, mid);
mergeSort(v, mid+1, upperBound);
merge(v, lowerBound, mid+1, upperBound);
System.out.println("first:"+lowerBound+"---------"+"last"+upperBound);
for(int i = lowerBound;i<=upperBound;i++){
System.out.println(v[i]);
}
System.out.println("-----------------------");
}
}
//merge方法
private static void merge(int[] v, int first, int mid, int last) {
int indexA, indexB;
int[] tempArray = new int[last - first + 1];
int temp = 0;
indexA = first;
indexB = mid;
// 比较两个sublist,然后将完成比较的变量按着顺序放入到一个数组临时变量里面
while (indexA < mid && indexB <= last) {
if (v[indexA] < v[indexB]) {
tempArray[temp] = v[indexA];
indexA++;
temp++;
} else {
tempArray[temp] = v[indexB];
indexB++;
temp++;
}
}
// 将剩余变量插入到数组当中
while (indexA < mid) {
tempArray[temp++] = v[indexA++];
}
while (indexB <= last) {
tempArray[temp++] = v[indexB++];
}
// 將tempArray中的数据转换到数组v当中
for (int i = 0; i < temp; i++) {
v[first++] = tempArray[i];
}
}
}
运行结果:
first:0---------last0
10
first:1---------last1
4
first:0---------last1
4
10
-----------------------
first:2---------last2
6
first:0---------last2
4
6
10
-----------------------
first:3---------last3
2
first:4---------last4
15
first:3---------last4
2
15
-----------------------
first:0---------last4
2
4
6
10
15
-----------------------
first:5---------last5
14
first:6---------last6
56
first:5---------last6
14
56
-----------------------
first:7---------last7
27
first:5---------last7
14
27
56
-----------------------
first:8---------last8
16
first:9---------last9
23
first:8---------last9
16
23
-----------------------
first:5---------last9
14
16
23
27
56
-----------------------
first:0---------last9
2
4
6
10
14
15
16
23
27
56
-----------------------
2
4
6
10
14
15
16
23
27
56
归并排序的效率:
归并排序的运行时间是O(N*logN)。如何知道这个时间呢?首先,看在这个算法执行的过程当中,如何计算一个数据项被复制的次数以及和其他数据项比较的次数。假设复制和比较是最费时的操作,递归的调用和返回不增加额外的开销。
复制的次数和N*logN成正比。
比较次数:最小的比较次数总是正在被递归的数据项个数的一半,最大的比较次数比数据项的个数少一。