归并排序算法(Java实现)

一:基本思想

        该算法采用经典的分治策略,分治法将问题分成一堆小的问题,而治的阶段则将各个阶段得到的答案合并到一起。也就是分到不可再分,再进行排序,俩个单独数进行排序合并成一组,不同组之间再进行排序合并,直到全部排序合并完成。

二:图解+文字

1)将数组分成不可再分的阶段
2)治的阶段(大白话解释)

(1)最终分成单独的数

        8 4 5 7 1 3 6 2                 合并4次(8和4,5和7,1和3,6和2)

(2)俩组比较大小,从小到大放到新数组里,全部比较完成后,新数组复制回原数组

        4,8       5,7        1,3        2,6                 合并2次

 (3)俩组俩组比较,同(2)

        4,5,7,8        1,2,3,6                        合并1次

 (4)最后一次比较,同(2)

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

通过如上的分析,可以得到

共合并 :7 次=数据总长-1

三:优缺点

优点:稳定的排序算法

           预测的性能比较好

缺点:占用的空间较多,当数据量特别大的时候,备用数组会占用额外的内存(看代码示例)

           不适用于小型数据集

四:代码实现

        简洁明了,代码每一步都有注释

import java.util.Arrays;

public class MergetSort {
    public static void main(String[] args) {
        int[] arr={8,4,5,7,1,3,6,2};
        //temp 对应备用数组
        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,mid, right, temp);
        }
    }

    //合并的函数
    public static void merge(int[] arr,int left,int mid,int right,int[] temp){
        //定义左面数组开始循环的下标
        int i=left;
        //定义右面数组开始循环的下标
        int j=mid+1;
        //定义数组temp的初始下标
        int k=0;

        //第一步:把左右俩边的(有序)数组按照规则填充到temp数组里面
        //直到有一边数组填充完毕
        while (i <= mid && j <= right){
            if (arr[i] <= arr[j]){
                temp[k++]=arr[i++];
            }else{
                temp[k++]=arr[j++];
            }
        }
        //第二步,将剩余未填充完毕的数组全部填充到temp中
        while (i <= mid){
            temp[k++]=arr[i++];
        }

        while (j <= right){
            temp[k++]=arr[j++];
        }

        //第三步:temp数组赋值到arr数组里面
        //注: 并不是从头全部拷贝回到arr数组里面,
        /* 原因:
        *       如上分成了不同组,当填充前俩个 8 和 4的时候,tempLeft=0,right=1
        *       填充5 和 7 的时候,tempLeft=2,right=3
        *       填充1 和 3 的时候,tempLeft=4,right=5
        *       填充 4 8 和 5 7 的时候,tempLeft=0,right=3
        *       填充 1 3 和 2 6 的时候,tempLeft=4,right=7
        *       最后依次才是0 和 7
        * 每次填充的数都是temp下标对应的位置
        */
        int t=0;
        int tempLeft=left;
        while (tempLeft <= right){
            arr[tempLeft]=temp[t];
            tempLeft+=1;
            t+=1;
        }

    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值