归并排序 及Java实现

一、归并排序的思想

先使子序列有序,再使子序列段间有序,
将两个有序序列合成一个,称为二路归并
在待排序数据中,默认每个单独的数据都是有序的,每两个数据分为一个归并段,段内排序;每四个数据分为一个归并段,段内排序;每八个数据分为一个归并段,段内排序……直到所有数据有序(因为是按偶数分段的,所以当待排序数据个数为奇数时,最后总会剩余一个单独的数据,将其作为一个归并段就行)

1、复杂度、稳定性

  • 时间复杂度:最好情况:O(nlog2n)
    最坏情况:O(nlog2n)
  • 空间复杂度:O(n)
  • 稳定性: 稳定

2、图解

在这里插入图片描述
在归并时,要进行段内排序,定义四个变量:start1, end1, start2, end2. 分别表示相邻两个归并段的起始位置和结束位置。开始排序:判断start1和start2的大小,start1<start2时,将start1放入新的数组的第一个位置,start1++,再和start2比较,小的那个数的下标+1,直到start1>end1,将剩余的值按序放入新数组。如 下图:
在这里插入图片描述

二、代码

public class TestDemo2 {
    public static void merge(int[] array,int gap) {//每组的元素个数
        int[] tmpArr =  new int[array.length];  //定义新数组,用来保存每次归并结束的数据顺序。
        int i = 0;  //tmpArr的下标
        int start1 = 0; 
        int end1 = start1+gap-1;
        int start2 = end1+1;
        int end2 = start2+gap-1 < array.length ? start2+gap-1 : array.length-1;

        while (start2 < array.length) {//说明此时有两个对归并段
            //两个归并段都有数据
            while(start1 <= end1 && start2 <= end2) {
           //判断s1和s2,小的值放入tmpArr,并且下标后移一位继续比较,直到开始位置>结束位置,退出while
                if(array[start1] < array[start2]) {
                    tmpArr[i++] = array[start1++];
                }else {
                    tmpArr[i++] = array[start2++];
                }
            }
            while (start1 <= end1) {
                tmpArr[i++] = array[start1++];
            }
            while (start2 <= end2) {
                tmpArr[i++] = array[start2++];
            }
            //确定下一个归并段的开始和结束位置
            start1 = end2+1;
            end1 = start1+gap-1;
            start2 = end1+1;
            end2 = start2+gap-1 < array.length ? start2+gap-1 : array.length-1;
        }
        while (start1 < array.length) {
            tmpArr[i++] = array[start1++];
        }
        for (int j = 0; j < tmpArr.length; j++) {
            array[j] = tmpArr[j];
        }
    }
    public static void mergeSort(int[] array) {
        for (int i = 1; i < array.length; i *= 2) {
            merge(array,i);
        }
    }





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值