首先来决一个基本的问题:如何合并两个有序序列?
同样,我们也采取图形演示的方法,来一步一步解决问题,假设我们现在存在两个有序序列:1,3,5和2,4,6,7.
那么我们首先应该在脑海中画出这样的一副图形:
到现在,我们已经有解决问题的思路了:
比较这两个序列的第一个元素,谁较小就输出谁,,然后将较小的元素从原队列删除.如此往下进行,如果某个队列为空,则直接将另一个队列中元素依序输出就好.
按照上面的思路,整个过程用图形演示:
1. 选取较小元素
2. 选取较小元素
3. 选取较小元素
4. 选取较小元素
5. 选取较小元素,此时队列arr1已经为空了,因此后面只需要依次输出arr2中的元素即可
6. 输出元素
7. 输出元素
到现在整个过程已经描述清楚了.在具体的代码实现过程中,删除操作可以用移动下标来实现(许多操作,其实换个角度来想的)
代码实现为:
public static void merge(int[] arr, int start, int mid, int end, int[] temp) {
int m = mid;
int n = end;
int i = start;
int j = mid + 1;
int z = 0;
while (i <= m && j <= n) {
if (arr[i] < arr[j]) {
temp[z++] = arr[i++];
} else {
temp[z++] = arr[j++];
}
}
while (i <= m) {
temp[z++] = arr[i++];
}
while (j <= n) {
temp[z++] = arr[j++];
}
for (i = 0; i < z; i++)
arr[start + i] = temp[i];
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
现在我们来总结一下:两个有序队列可以很容易的合并成一个有序队列,合并的效率也是比较高的,可以达到O(n).
反向思考一下,任何一个序列(n>1)都可以被拆分成两个子序列,如果这两个子序列是有序的,那么可以很容易的将这两个子序列合并成有序序列。
ok,现在我们来回忆一下分治法:
把一个复杂的问题分成两个或更多的相同或相似的子问题,再把子问题分成更小的子问题……直到最后子问题可以简单的直接求解,原问题的解即子问题的解的合并。
结合我们刚才思考的,我们可以设想:任何一个序列(n>1),都可以不断的被一分为二,直到最后的序列中只有一个元素,只有一个元素的序列当然是有序的。
现在我们已经有一种排序的新思路了:为了让原始序列arr有序,可将它分成A,B两个序列,为让A,B两个序列有序,可以继续将A序列拆成A1,A2两个序列,如此拆分下去,直到序列中只有一个元素。对于B序列也是同样的操作。拆分完毕之后,再合并相近的两个序列就行。
恭喜你,一步一步找到一种排序的新思路——归并排序。现在我们要做的就是通过递归分解数列,然后通过合并就可以完成归并排序了。
实现代码如下:
public class MergeSort {
public static void main(String[] args) {
int[] arr3 = {1, 2, 5, 4};
int[] temp = new int[arr3.length];
sort(arr3, 0, arr3.length - 1, temp);
for (int i = 0; i < temp.length; i++) {
System.out.print(temp[i] + " ");
}
}
public static void sort(int[] arr1, int start, int end, int[] temp) {
if (start < end) {
int mid = (start + end) / 2;
System.out.println("mid " + mid + " " + start + ">" + mid + "---" + (mid + 1) + ">" + end);
sort(arr1, start, mid, temp);
sort(arr1, mid + 1, end, temp);
merge(arr1, start, mid, end, temp);
}
}
public static void merge(int[] arr, int start, int mid, int end, int[] temp) {
int m = mid;
int n = end;
int i = start;
int j = mid + 1;
int z = 0;
while (i <= m && j <= n) {
if (arr[i] < arr[j]) {
temp[z++] = arr[i++];
} else {
temp[z++] = arr[j++];
}
}
while (i <= m) {
temp[z++] = arr[i++];
}
while (j <= n) {
temp[z++] = arr[j++];
}
for (i = 0; i < z; i++)
arr[start + i] = temp[i];
}
}
--------------------- 本文来自 江湖人称小白哥 的CSDN 博客 ,全文地址请点击:https://blog.csdn.net/dd864140130/article/details/50859687?utm_source=copy