归并排序
前言
第一篇文章,只是想随便写点啥。聊一下排序算法吧,时时勤拂拭。我们并不需要关注所有排序算法的实现,多数的作为了解即可。只有其中少数优秀且经典的排序算法我们才需要掌握。例如归并排序、快速排序、堆排序。本篇就来讲下归并排序。归并排序不仅是优秀的排序算法,所用到的分治法更是经典思路。
算法思路
整体思路
当你已经熟悉这个算法,仅仅看上面的图示已经可以把整个的排序过程了然于胸。首先将待排序的元素分成大小大致相等的两个子序列,然后再把子序列分成大小大致相等的两个子序列,如此下去,直到分解成一个元素为止。这时含有一个元素的子序列都是有序的。然后执行合并操作,将两个有序的子序列合并为一个有序序列,如此下去,直到所有的元素都合并为一个有序序列。
核心问题
整体的算法中涉及到两个问题,一是拆分数组成两个大小大致相等的数组,二是合并两个有序数组,问题一是容易解决的。问题在于问题二如何解决。我们首先申请一个大小足够的新数组,然后对两个有序数组本着谁当前元素小谁往新的数组插入。最后再处理下有剩余元素的数组即可。核心算法如下:
/**
* 首先,实现下合并两个有序数组的方法,合并两个有序数组使得原来数组依旧有序,
* 方法return时将合并的两个有序数组返回
*/
private static int[] mergeTwoSortedArray(int[] array1, int[] array2) {
// 申请新数组
int[] array = new int[array1.length + array2.length];
// 定义各个数组标兵
int i = 0, j = 0, k = 0;
while (i < array1.length && j < array2.length) {
if (array1[i] <= array2[j]) {
array[k++] = array1[i++];
} else {
array[k++] = array2[j++];
}
}
// 当上面的循环进行完毕之后,依旧可能存在未完成的数字归纳,那么我们归纳完成
while (i < array1.length) {
array[k++] = array1[i++];
}
while (j < array2.length) {
array[k++] = array2[j++];
}
return array;
}
至此,我们的整个算法都可以完成了,如下:
import java.util.Arrays;
/**
* 二路归并排序
*
* @author : wuwensheng
* @date : 17:17 2021/11/9
*/
public class MergeSort {
/**
* 首先,实现下合并两个有序数组的方法,合并两个有序数组使得原来数组依旧有序,
* 方法return时将合并的两个有序数组返回
*/
private static int[] mergeTwoSortedArray(int[] array1, int[] array2) {
System.out.println("prepare to merge array1:" + Arrays.toString(array1));
System.out.println("prepare to merge array2:" + Arrays.toString(array2));
// 申请新数组
int[] array = new int[array1.length + array2.length];
// 定义各个数组标兵
int i = 0, j = 0, k = 0;
while (i < array1.length && j < array2.length) {
if (array1[i] <= array2[j]) {
array[k++] = array1[i++];
} else {
array[k++] = array2[j++];
}
}
// 当上面的循环进行完毕之后,依旧可能存在未完成的数字归纳,那么我们归纳完成
while (i < array1.length) {
array[k++] = array1[i++];
}
while (j < array2.length) {
array[k++] = array2[j++];
}
System.out.println("merge two array result:" + Arrays.toString(array));
return array;
}
private static int[] mergeSortMethod(int[] array) {
// 当数组长度来到1的时候,可以执行归并了
if (array.length <= 1) {
return array;
}
// 首先,将数组拆为两个
int number = array.length >> 1;
int[] array1 = Arrays.copyOf(array, number);
int[] array2 = Arrays.copyOfRange(array, number, array.length);
System.out.println("original array:" + Arrays.toString(array));
System.out.println("left array:" + Arrays.toString(array1));
System.out.println("right array:" + Arrays.toString(array2));
System.out.println("--------------------------------------");
return mergeTwoSortedArray(mergeSortMethod(array1), mergeSortMethod(array2));
}
public static void main(String[] args) {
int[] array2 = {35, 101, -88, 21, 1, -6, 9, -1, 44, 33};
int[] ints = mergeSortMethod(array2);
for (int anInt : ints) {
System.out.println(anInt);
}
}
}
我们加入一些输出语句,来观察下整个运行过程:
非常清晰,先拆分再合并,本篇到此。