归并排序(merge sort)

归并排序

    这是一种分治法的应用,就是对于一个待排序的序列,将它一分为二,二分为四……,分到最后,每一个序列中只会包含一个元素,这时,每一个小序列就已经有序了(因为只有一个元素,所以肯定是有序的)。然后将其两两归并排序,……四合为二,二合为一。这样就能完排序功能。

130143_xE8b_1452675.jpg

该排序算法有两个方法:

1.合并方法merge(),合并一个在某一位置分开,两边子序列分别有序的序列。

2.归并排序方法mergeSort(),这个方法递归调用,完成序列的拆分排序。

/**
     * @Description 合并排序一个在startIndex到minIndex位置有序,且在midIndex到endIndex上有序的序列
     * @param srcArray
     *            源数组,且该数组在startIndex到midIndex位置上有序,在midIndex到endIndex上有序
     * @param targetArray
     *            目标数组,排序完成之后的数组,起始位置为srcArray的起始位置
     * @param startIndex
     *            排序开始位置 (不一定在srcArray的开始位置)
     * @param midIndex
     *            排序中间位置
     * @param endIndex
     *            排序结束位置
     * @return
     */
    public static void merge(int[] srcArray, int[] targetArray, int startIndex,
            int midIndex, int endIndex) {
        // 注意目标数组的起始位置k是startIndex,而非0,因为srcArray的起始位置要和targetArray中的起始位置相同
        int i = startIndex, j = midIndex + 1, k = startIndex;

        // 这里i,j用来指示由srcArray拆分出的两个有序子序列的起始位置
        // 当某一个数组中的数字已经用完,那么就不用再循环比较了,直接将另一个数组中剩下的数字拼接到新数组中即可
        while (i < midIndex + 1 && j < endIndex + 1) {
            if (srcArray[i] < srcArray[j]) {
                targetArray[k++] = srcArray[i++];
            } else {
                targetArray[k++] = srcArray[j++];
            }
        }

        // 如果startIndex到midIndex数组中还剩下有数,那么将其拼接到目标数组targetArray中
        while (i < midIndex + 1) {
            targetArray[k++] = srcArray[i++];
        }

        // 如果midIndex到endIndex数组中还剩下有数,那么将其拼接到目标数组targetArray中
        while (j < endIndex + 1) {
            targetArray[k++] = srcArray[j++];
        }
    }

    /**
     * @Description 归并排序(递归),这个方法为什么需要一个开始位置和结束位置?因为这个数组在递归排序过程中逻辑上会拆分成很多小序列,
     *              (一分为二,二分为四……) 直到一个序列只包含一个数为止,
     *              而这个startIndex和endIndex则是指示这些逻辑上的小数组在源数组中的正确位置。
     * @param srcArray
     *            待排序数组
     * @param targetArray
     *            目标数组
     * @param startIndex
     *            开始位置
     * @param endIndex
     *            结束位置
     * @return
     */
    public static void mergeSort(int[] srcArray, int[] targetArray,
            int startIndex, int endIndex) {
        int midIndex;
        int[] tempArray = new int[1024]; // 该数组为临时数组,大小需要按照需要进行更改,必须>=源数组

        // 特别注意:这是递归的出口,也就是指当序列一分为二,二分为四……,当序列被折分到子序列中只剩下一个元素的时候,
        // 那么这个子序列就算是有序序列了(因为有一个元素,所以肯定算是有序列的)。
        // 将其直接存放于target目标数组中即可
        if (startIndex == endIndex) {
            targetArray[startIndex] = srcArray[startIndex];
        } else {
            midIndex = (startIndex + endIndex) / 2;
            mergeSort(srcArray, tempArray, startIndex, midIndex); // 递归排序左边的序列
            mergeSort(srcArray, tempArray, midIndex + 1, endIndex); // 递归排序右边的序列

            merge(tempArray, targetArray, startIndex, midIndex, endIndex); // 递归将排序好的序列(存放于temp中)进行2路归并
        }
    }


转载于:https://my.oschina.net/u/1452675/blog/202405

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值