数据结构 —— 归并排序

归并排序方法就是把一组n个数的序列,折半分为两个序列,然后再将这两个序列再分,一直分下去,直到分为n个长度为1的序列。然后两两按大小归并。如此反复,直到最后形成包含n个数的一个数组。

合并有序序列

原有两个有序数组:

 创建一个长度为两个序列长度和的数组,s1、s2游标在原序列进行遍历,按大小比较放入新数组中。

无序序列怎么变有序

先将一个无序序列拆分成小组,再进行有序序列合并。

 

归并排序流程:

  1. 不断拆分,直到所有数据变成一个一组为止

  2. 再进行合并,合并过程中借助一个临时空间进行排序

  3. 以此类推,最后数组就会变得有序

时间复杂度:

时间复杂度 = 轮数 * 每一轮里的时间复杂度 = O(nlogn)

第一轮:一个数组 2^0

第二轮:两个数组 2^1

第三轮:四个数组 2^2

........

第k轮:2 ^ (k-1) = n 即:k = log2n

每一轮里的时间复杂度:n

代码实现:

通过递归方法实现。

递归关系:
       当需要向左拆分时,f(arr, left, i); 当需要向右拆分时,f(arr, i+1, right)

递归出口:
       left = right

import java.util.Arrays;

public class mergeSort {
        public static void main(String[] args) {
                int[] arr = new int[] {5,7,4,2,0,3,1,6};
                mergeSort(arr, 0, arr.length-1);
                System.out.println(Arrays.toString(arr));
        }
        
        /*拆分*/
        public static void mergeSort(int[] arr, int left, int right) {
                //递归出口
                if(left >= right) {
                        return;
                }
                int i = (left + right)/2;
                //向左拆分
                mergeSort(arr, left, i);
                //向右拆分
                mergeSort(arr, i+1, right);
                //调用合并的方法
                merge(arr, left, i, right);
        }
        
        /*合并*/
        public static void merge(int[] arr, int left, int middle, int right) {
                //第一个序列
                int s1 = left;
                //第二个序列
                int s2 = middle+1;
                //定义临时数组
                int[] temp = new int[right-left+1];
                //定义游标遍历临时数组
                int index = 0;
        
                //比较大小,将小的数放入临时数组中
                while(s1<=middle && s2<=right) {
                        //s1小
                        if(arr[s1]<=arr[s2]) {
                                temp[index] = arr[s1];
                                index++;
                                s1++;
                        }else {//s2小
                                temp[index] = arr[s2];
                                index++;
                                s2++;
                        }
                }
                //当右半组都放入临时数组后,将左半部分剩下的数依次放入
                while(s1<=middle) {
                        temp[index] = arr[s1];
                        index++;
                        s1++;
                }
                //当左半组都放入临时数组后,将左半部分剩下的数依次放入
                while(s2<=right) {
                        temp[index] = arr[s2];
                        index++;
                        s2++;
                }
                //把临时数组当中的数据返回原数组
                for(int j=0; j<temp.length; j++) {
                        arr[j+left] = temp[j];
                }
        }  
}

其中,把临时数组当中的数据返回原数组时,j+left 的原因:

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值