参考连接:
https://blog.youkuaiyun.com/morewindows/article/details/6678165/
SteveWang
www.cnblogs.com/eniac12/p/5329396.html
1.递归的归并排序的思路
归并排序是由若干次组内元素的归并排序一起完成的.
首先,对两个已经有序的数组进行合并的操作比较简单,代码如下
public static long[] mergeSortArr(long arrA[], long arrB[]) {
int countA = arrA.length;
int countB = arrB.length;
long arrMerge[] = new long[countA + countB];
int indexA = 0, indexB = 0, indexMerge = 0;
while (indexA < countA && indexB < countB) {
if (arrA[indexA] < arrB[indexB]) {
arrMerge[indexMerge++] = arrA[indexA++];
// indexA++;
} else {
arrMerge[indexMerge++] = arrB[indexB++];
// indexB++;
}
// indexMerge++;
}
while (indexA < countA) {
arrMerge[indexMerge++] = arrA[indexA++];
}
while (indexB < countB) {
arrMerge[indexMerge++] = arrB[indexB++];
}
return arrMerge;
}
这个操作可以理解为一次归并排序,但是对于任意数组,数据可能不是有序的,那么如何进行有序数组的归并呢? 既然数组内数据不是有序的,那么我们就把数组分割,一分为二,再一分为二……直到分割成每个组内只有一个数据,每个数据可以理解为一个个长度为1的有序数组,然后对长度为1的数组进行归并排序,归并之后,数组内会存在长度更大的有序数组,再对这些有序数据进行归并,一点点叠加,直到归并结束.
归并排序的动图
2.递归的归并排序的实现
public class MergeSort {
// 合并有序数组
public static void mergeSortArr(long arr[], int start, int mid, int end,
long arrMerge[]) {
int s1 = start;// start 1
int s2 = mid + 1;// start 2
int limit1 = mid;
int limit2 = end;
int mergeIndex = 0;
while (s1 <= limit1 && s2 <= limit2) {
if (arr[s1] < arr[s2]) {
arrMerge[mergeIndex++] = arr[s1++];
} else {
arrMerge[mergeIndex++] = arr[s2++];
}
}
while (s1 <= limit1) {
arrMerge[mergeIndex++] = arr[s1++];
}
while (s2 <= limit2) {
arrMerge[mergeIndex++] = arr[s2++];
}
// 将排好序的数据存到arrMerge中
for (int i = 0; i < mergeIndex; i++) {
arr[start + i] = arrMerge[i];
}
}
// 归并排序递归思路
public static void mergeSort(long arr[], int start, int end,
long arrMerge[]) {
if (start < end) {// 递归的结束条件:数组被分割成一个个数据(如果只有一个数据,那么start==end)
int mid = (start + end) / 2;
mergeSort(arr, start, mid, arrMerge);// 对左半侧实施归并
mergeSort(arr, mid + 1, end, arrMerge);// 对右半侧实施归并
mergeSortArr(arr, start, mid, end, arrMerge);
}
}
public static void main(String[] args) {
long a[] = { 1, 2, 3, 4, 5, 77, 3, 4, 66, 2, 11, 4, 5 };
long mer[] = new long[a.length];
mergeSort(a, 0, a.length - 1, mer);
if (mer != null) {
for (int i = 0; i < mer.length; i++) {
System.out.println(mer[i]);
}
}
}
}
3.递归的归并排序的效率
递归排序分为两个部分:
1.将数据分割为一个个长度为一的数据
2.对这些数据进行归并
将数据分割为一个个长度为一的数据的时间复杂读为O(logN)(对长度为n的数组拆分,第一次均分为2份,第二次4份,第三次8份……最终每份只有一个元素需要拆分
log2n
l
o
g
2
n
次)对有序数据进行归并排序,与归并的两个数组的长度成正比,因此时间复杂度为O(N),那么归并排序的时间复杂度就是O(NlogN)了
4.题外(教训):debug的重要性
自己在编写归并排序的mergeSortArr方法时,一直报错数组越界,从头看到尾,仔仔细细看了n遍,都没有发现错误.最后实在没办法,用System.out.println()+debug找到问题出现在边界值上,(即<是否加=的情况).我们在写代码时,往往会觉得自己的代码逻辑没有问题,千看万看就是找不到问题点,因为我们往往会顺着我们的思路读代码,但是程序的执行往往并不是按照我们心中所想的步骤进行的,这时就需要多多debug了.