归并排序学习笔记

思想:将一个有序序列递归分割为一个个单一的数据,分到不可再分割之后就回退到上一步,将数据两两有序合并合并到一个临时数组中去,再将合并过去的数据拷贝到原来的数组中,以此类推,反递归到最开始的地方,序列就变成一个有序序列了。

第一步:分割数组

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;//记录右边数据开始的位置
        int t = 0;//记录temp数组中的位置

        /*
        * 1、先把比较左右两边的数据并添加到temp数组,直到一边数据完全被填充到temp数组
        * */
        while (i <= mid && j <= right){
            if (arr[i] < arr[j]){
                temp[t] = arr[i];
                t += 1;
                i += 1;
            }else {
                temp[t] = arr[j];
                t += 1;
                j += 1;
            }
        }

        /*
        * 2、此时将剩下的另一边的数据全部填充到temp
        * */
        while (i <= mid){
            //说明左边的数据没有填充完,直接把左边的数据给填到temp中去
            temp[t] = arr[i];
            t += 1;
            i += 1;
        }
        while (j <= right){
            //说明右边的数据没有填充完,直接把右边的数据给填到temp中去
            temp[t] = arr[j];
            t += 1;
            j += 1;
        }

        /*
        * 3、将temp数据拷贝到arr数组
        * 此处注意,这里只是将本次归并好的数据拷贝到arr数组,并不是将所有的数据拷贝
        * */
        t = 0;
        int templeft = left;//记录的是原数组中开始合并数据的位置
    	//例如是原数组是int arr[] = {1,3,5,6,8,7}它第一次合并的是1、3,则left=,right=1
    	//到第二次的时候是将5和{1,3}合并,left=0,right=2;
    	//第三次将6和8合并,left=3,right=4;
    	//第四次时间7和{6,8}合并,left=3,right=5;
    	//第五次是将{1,3,5}和{6,7,8}合并,left=0,right=5,合并的次数是arr.length - 1;
        while (templeft <= right){
            arr[templeft] = temp[t];
            t += 1;
            templeft += 1;
        }

    }

完整代码

public class MergeTest {

    public static void main(String[] args) {

        //int arr[] = {1,3,5,6,8,4,7,2};
        // 创建要给 80000 个的随机的数组
        int[] arr = new int[80000000];
        for (int i = 0; i < 80000000; i++) {
            arr[i] = (int) (Math.random() * 80000000);
            // 生成一个[0, 8000000) 数
        }
        int temp[] = new int[arr.length];
        //System.out.println(Arrays.toString(arr));
        System.out.println("排序前");
        Date data1 = new Date();
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String date1Str = simpleDateFormat.format(data1);
        System.out.println("排序前的时间是=" + date1Str);
        MergeTest.MergeSort(arr, 0, arr.length - 1, temp);
        System.out.println("排序后");
        Date data2 = new Date();
        String date1Str2 = simpleDateFormat.format(data2);
        System.out.println("排序后的时间是=" + date1Str2);
        //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;//记录右边数据开始的位置
        int t = 0;//记录temp数组中的位置

        /*
        * 1、先把比较左右两边的数据并添加到temp数组,直到一边完全填充到temp数组
        * */
        while (i <= mid && j <= right){
            if (arr[i] < arr[j]){
                temp[t] = arr[i];
                t += 1;
                i += 1;
            }else {
                temp[t] = arr[j];
                t += 1;
                j += 1;
            }
        }

        /*
        * 2、将剩下的另一边的数据全部填充到temp
        * */
        while (i <= mid){
            //说明左边的数据没有填充完,直接把左边的数据给填到temp中去
            temp[t] = arr[i];
            t += 1;
            i += 1;
        }
        while (j <= right){
            //说明右边的数据没有填充完,直接把右边的数据给填到temp中去
            temp[t] = arr[j];
            t += 1;
            j += 1;
        }

        /*
        * 3、将temp数据拷贝到arr数组
        * 此处注意,这里只是将本次归并好的数据拷贝到arr数组,并不是将所有的数据拷贝
        * */
        t = 0;
        int templeft = left;
        while (templeft <= right){
            arr[templeft] = temp[t];
            t += 1;
            templeft += 1;
        }

    }
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值