JAVA 归并排序算法(详细实现过程介绍)

归并排序是一个典型的基于分治的递归算法。它不断地将原数组分成大小相等的两个子数组,直到划分的子数组大小为1的过程。此算法操作即为:。然后将划分的有序子数组合并成一个更大的有序数组,此算法操作即为:

它将数组平均分成两部分: mid= (left + right)/2,当数组分得足够小时,即:数组中只有一个元素时,只有一个元素的数组自然而然地就可以视为是有序的,此时就可以进行合并操作了。因此,合并两个有序的子数组,是从 只有一个元素 的两个子数组开始合并的。

比如初始数组:[8, 4, 5, 7, 1, 3, 6, 2]

①分成了两个大小相等的子数组:[8, 4, 5, 7]    [1, 3, 6, 2]

②再划分成了四个大小相等的子数组:[8, 4]   [5, 7]    [1, 3]    [6, 2]

③此时,left < right 还是成立,再分:[8]   [4]   [5]    [7]    [1]     [3]    [6]   [2]

此时,有8个小数组,每个数组都可以视为有序的数组了!!!

第一轮合并

merge([8],[4]) 得到 [4,8]

merge([5],[7]) 得到[5,7]

merge([1],[3]) 得到[1,3]

merge([6],[2]) 得到[2,6]

第二轮合并

merge( [4,8],[5,7]) 得到 [4,5,7,8]

merge( [1,3],[2,6]) 得到 [1,2,3,6]

第三轮合并

merge( [4,5,7,8], [1,2,3,6]) 得到 [1,2,3,4,5,6,7,8]

最终得到 有序数组 [1,2,3,4,5,6,7,8]。

以下为图示()过程:

以下为图示()过程:

1<4将1填入临时数组 

 

2<4将2填入临时数组

3<4将3填入临时数组

4<8将4填入临时数组

5<8将5填入临时数组

7<8将7填入临时数组

8<9将8填入临时数组

只剩下9,将9填入数组的最后位置

最终数组

实现说明:

① 以mid为分隔线分别向左、向右递归拆分数组。

②创建一个临时数组temp,用来保存两个子数组临时合并的结果。

③使用while循环,当左边的数组元素小于等于mid且右边的数组元素小于等于最右侧下标时,就将左边的元素填充到 临时数组temp,且左边数组下标后移,temp数组下标后移。否则,将右边的元素填充到 临时数组temp,且右边数组下标后移,temp数组下标后移。

④不满足上述条件时,如果左边的数组剩余元素的下标小于等于mid,则代表左侧数组还有剩余元素未填充到temp中,此时循环将剩余的左边数组元素填充到temp中。如果右边的数组剩余元素的下标小于等于最右侧下标时,则代表右侧数组还有剩余元素未填充到temp中,此时循环将剩余的右边数组元素填充到temp中。

⑤合并完成,此时临时数组中的元素为有序的数组,将临时数组复制到指定排序的数组arr中即可。

 

代码实现:

import java.util.Arrays;

public class MergeSort {
    public static void main(String[] args) {
        int [] arr = {8, 4, 5, 7, 1, 3, 6, 2};
        int temp[] = new int[arr.length];
        mergeSort(arr,0,arr.length-1,temp);
        System.out.println(Arrays.toString(arr));

    }

    public static void mergeSort(int[]arr,int left,int right,int[] temp){
        if(left<right) {
            int mid = (left + right) / 2;
            //向左递归拆分
            mergeSort(arr, left, mid, temp);
            //向右递归拆分
            mergeSort(arr, mid + 1, right, temp);
            //合并拆分后的数组
            merge(arr, left, right, mid, temp);
        }
    }

    public static void merge(int[]arr,int left,int right,int mid,int[] temp){
        int index=0; //temp数组下标
        int i = left;//左边开始下标
        int j = mid+1; //右边开始下标

        //第一步,如果左边的数小于右边的数,就将左边的数填充到temp数组中,否则将右边的数填充到temp数线中
        while (i<=mid && j<=right){
            if(arr[i]<=arr[j]){
                temp[index] = arr[i];
                index++;
                i++;
            }else{
                temp[index] = arr[j];
                index++;
                j++;
            }
        }

        //第二步,将剩下的数填充到temp数组中
        while (i<=mid){
            temp[index] = arr[i];
            index++;
            i++;
        }
        while (j<=right){
            temp[index] = arr[j];
            index++;
            j++;
        }

        //第三步,将临时数组temp 复制到arr中
        int templeft = left;
        index =0;
        while (templeft<=right){
            arr[templeft] = temp[index];
            templeft++;
            index++;
        }
    }
}

输出结果:

[1, 2, 3, 4, 5, 6, 7, 8]

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值