并归排序算法

归并排序

1、归并排序原理

      归并排序是采用了分治思想的一种排序算法。它是不断的将原数组分成大小相等的两个子数组(长度也可能相差1),最终当划分的子数组长度为1时,将这些只包含一个元素的子数组视为有序序列,然后将这些划分的有序的子数组合并成更大的有序数组。基本原理是将带排序序列分成多个子序列,分别进行递归排序,然后将已排好序的子序列归并在一起,得到完整的有序序列

2、实例分析

归并排序动态图

1) 假设有一个无序的列表如:[10, 17, 50, 7, 30, 24, 27, 45]

将数组进行平分,直到均分后的元素个数为1

图片

2) 如上图所示,当分为单个时,此时进行排序,怎么排序那?因为10和17是一组,所以两者进行排序为10、17,然后50和7进行排序,排序结果为7、50,那30、24排序后变成24、30,最后的27、45排序后为24、45

图片

3) 然后两组之间再进行排序,首先10和7对比,对比结果7小,那么将7放到一个空列表中,然后10和50进行对比,对比结果10小,将10追加到刚才的空列表中,排在7后面,然后17和50对比,对比结果17比较小,然后追加到空列表中,然后将50追加到空列表中,以此类推,那么排序结果如下图

图片

继续按照第三步进行数组的合并,生成最终的排好序的数组

3、实例分析总图

对9、5、2、7、12、4、3、1、11进行归并排序总图

图片

4、代码实现归并排序

// 分解数组

public void mergeDiv(int[] arrs, int left, int right) {
    if (left < right) {
        int[] temp = new int[arrs.length];
        // 因为要均分,所以先找到中间位置
        int mid = (left + right) / 2;
        mergeDiv(arrs, left, mid);
        mergeDiv(arrs, mid + 1, right);
        // 分完之后,进行merge操作
        merge(arrs, left, mid, right);
    }
}
// 合并数组并排序
private void merge(int[] arrs, int left, int mid, int right) {
    int[] temp = new int[right - left + 1]; // 创建临时数组
    int i = left, j = mid + 1, k = 0;
    while (i <= mid && j <= right) {
        if(arrs[i]<arrs[j]){
            temp[k++] = arrs[i++];
        }else{
            temp[k++] = arrs[j++];
        }
    }

// 当左子数组还有元素时,将剩余元素追加到临时数组之后即可
    while(i<=mid){
        temp[k++] = arrs[i++];
    }

// 当右子数组还有元素时,将剩余元素追加到临时数组之后即可
    while(j<=right){
        temp[k++] = arrs[j++];
    }

// 将临时数组的值覆盖回原数组
    for(int m=0;m<temp.length;m++){
        arrs[left+m] = temp[m];
    }
}

5、时间复杂度分析

分解数组时每次将数组一分为二,直到分出元素个数为1为止,显然需要分割logn次;

合并的时候需要将左右两个子数组的元素全都遍历一次,进行n次的比较和添加操作,所以时间复杂度为O(nlogn)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值