归并排序

归并排序

归并排序的思想是将两个有序数组合并成一个新的有序数组的过程,所以要使用归并就必须保证待合并的两个数组本身是有序的。

归并排序的流程

需要一个中间数组,长度为两个待合并数组的长度之和,然后需要三个索引值,分别为左索引指向左数组(待合并数组一)0号索引位置,右索引指向右数组(待合并数组二)0号索引位置,遍历索引指向中间数组0号索引位置,然后开始对左索引位置值和右索引位置值作比较,将较小的数添加到中间数组并同时将中间索引和对应索引进行自增操作,但如果左索引位置值和右索引位置值相等,则先将左索引位置值添加到中间数组中,然后对左索引和中间索引进行自增操作。随着算法的进行,左右索引肯定会有一个先产生越界(即到数组末尾),这时另一个数组肯定还会有元素未添加到中间数组中,此时将另一个数组未添加到中间数组的值添加到中间数组中即可。

归并示例

这边提供一个归并实例:左数组{1,2,3},右数组{2,4,5}
交换过程及结果如下图所示

排序乱序数组

对于乱序数组如何使用归并排序?其实只需要通过递归的方式将分解产生的数组排好序之后,再执行归并流程即可,递归分解的过程中,一定会分解到数组中只存在一个元素的情况,这种情况下,单元素数组本身就是有序的,这时就可以进行归并流程,然后逐层的返回结果,最终得到排好序的整个数组,我们通过下面两张图了解递归是如何进行的:

对于上图中,数组{2,3,1,4,5,2}需要等待子数组{2,3,1}和{4,5,2}有序后才能进行归并排序,而数组{2,3,1}则需要等待子数组{2}和{3,1}有序后才能进行归并排序,对于数组{2}已经有序了,而数组{3,1}则需要等待子数组{3}和{1}有序才能进行排序,而此时{3}和{1}已经有序了,继而得到{1,3}并返回然后与{2}进行归并得到{1,2,3}并返回然后与递归放回的{2,4,5}进行归并得到最终排好序的数组{1,2,2,3,4,5},如下图所示

对应的算法代码为:

static void merge(int[] arr, int start, int end) {//归并排序
    if (start >= end) return;   //base case
    int mid = start + (end - start) / 2;
    merge(arr, start, mid);     //对左部分数组进行递归
    merge(arr, mid + 1, end);   //对有部分数组进行递归
    //左数组和右数组都有序之后申请中间数组空间进而开始归并流程
    int[] temp = new int[end - start + 1];
    int left = start, right = mid + 1, bounce = end, index = 0;
    //左右数组都未到边界
    while (left <= mid && right <= bounce)
        temp[index++] = arr[left] <= arr[right] ? arr[left++] : arr[right++];
    //右数组已经到达边界,对左数组剩余部分添加到中间数组
    while (left <= mid) temp[index++] = arr[left++];
    //左数组已经达到边界,对右数组剩余部分添加到中间数组
    while (right <= end) temp[index++] = arr[right++];
    //将排好序的部分写回到原数组中
    System.arraycopy(temp, 0, arr, start, temp.length);
}

测试排序结果

通过对数器的方式对排序结果的验证

public static void main(String[] args) {
    int size = 30;
    int[] arr1 = Utils.generateRandomArray(size, 100);
    int[] arr2 = new int[arr1.length];
    System.arraycopy(arr1, 0, arr2, 0, arr1.length);
    System.out.println("原数组:		" + Arrays.toString(arr1));
    Arrays.sort(arr1);
    System.out.println("内置排序后:	" + Arrays.toString(arr1));
    merge(arr2, 0, arr2.length - 1);
    System.out.println("归并排序后:	" + Arrays.toString(arr2));
}
原数组:	[4, 0, 15, 61, 42, 10, 86, 16, 30, 92, 29, 95, 94, 58, 98, 60, 2, 52, 89, 69, 49, 21, 3, 97, 53, 50, 96, 56, 56, 5]
内置排序后:	[0, 2, 3, 4, 5, 10, 15, 16, 21, 29, 30, 42, 49, 50, 52, 53, 56, 56, 58, 60, 61, 69, 86, 89, 92, 94, 95, 96, 97, 98]
归并排序后:	[0, 2, 3, 4, 5, 10, 15, 16, 21, 29, 30, 42, 49, 50, 52, 53, 56, 56, 58, 60, 61, 69, 86, 89, 92, 94, 95, 96, 97, 98]

如果对你有帮助,点个赞,或者打个赏吧,嘿嘿
整理不易,请尊重博主的劳动成果

原文地址:https://www.cnblogs.com/Mango-Tree/p/13267635.html