排序算法-6-归并排序

一、基本思想

归并排序:采用了分治策略(将问题分解成一些小问题,再逐个递归求解,最后再将各阶段的结果“修补”到一起)。
在这里插入图片描述

思路分析:

归并排序使用分治法(将问题分成一些小的问题然后递归求解),通过 “分解-合并-复制” 的步骤,将一组数排序。

  • 分解:将一组数从中间分成两份,再将每一份分成两份,直到每一份只有一个数;
  • 合并:通过一个temp临时数组,合并相邻有序子序列;
    (1)在待合并的两个有序子序列起始位置分别加一个指针,比较指针所指位置的数,将较小的数存入temp数组后,将那个指针向后移动,再比较大小将较小的数存入temp;
    (2)如果待合并的两个有序子序列中,有一组已经被全部添加到temp中了,那么将另一组中的剩余数顺序存入temp中;
  • 复制:将临时数组中排好序的数再复制到原数组中;

在这里插入图片描述

二、代码实现

package sort;

import java.util.Arrays;
import java.util.Date;

/**
 * 归并排序
 *
 * 思路分析:
 * 归并排序使用分治法(将问题分成一些小的问题然后递归求解),通过 "分解-合并-复制" 的步骤,将一组数排序。
 * 分解:将一组数从中间分成两份,再将每一份分成两份,直到每一份只有一个数;
 * 合并:通过一个temp临时数组,合并相邻有序子序列;
 * (1)在待合并的两个有序子序列起始位置分别加一个指针,比较指针所指位置的数,将较小的数存入temp数组后,将那个指针向后移动,再比较大小将较小的数存入temp;
 * (2)如果待合并的两个有序子序列中,有一组已经被全部添加到temp中了,那么将另一组中的剩余数顺序存入temp中;
 * 复制:将临时数组中排好序的数再复制到原数组中;
 */
public class MergeSort {
    public static void main(String[] args) {
        int[] arr = {8,4,5,3,1,7,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);
        }
    }

    /**
     * 合并两个有序列表
     * @param arr
     * @param left
     * @param right
     * @param mid
     * @param temp
     */
    public static void merge(int[] arr,int left,int right,int mid,int[] temp){
        int i = left;//左边序列的初始索引位置
        int j = mid+1;//右边序列的初始索引位置
        int t=0;//指向temp数组中的当前位置
        //第一步:
        //将待合并的两个有序序列从左到右比较大小并按照顺序存入temp中
       while(i<=mid && j<=right){
           if(arr[i]<arr[j]){
               temp[t] = arr[i];
               t++;
               i++;
           }else{
               temp[t] = arr[j];
               t++;
               j++;
           }
       }

        //第二步:
        //将有剩余的序列里边的元素顺序添加到temp中
        while (i<=mid){
            temp[t] = arr[i];
            t++;
            i++;
        }

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

        //第三步:
        //将temp中的数复制到愿数组 arr 中。注意:不是每次复制都从 arr原数组的第一个元素开始写,也不是每次复制都复制都对原数组的所有元素写。
        //每一次复制的元素写入时,从当前合并序列的left索引开始写入arr。
        t = 0;
        int tempLeft = left;//tempLeft指向写入arr原数组时的索引位置。即:每次写入的位置是left到right所在索引之间。tempLeft用于向后移动。
        while(tempLeft <= right ){
            arr[tempLeft] = temp[t];
            tempLeft++;
            t++;
        }

    }

}

三、性能对比

以80000个数据测试,耗时大约11ms
在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值