Java-归并排序

1.原理/思路

 归并排序的设计思路是:将待排序的数组分为两个字数组,分别对它们按同样的方式进行排序,最后将两个有序子数组
 归并成一个有序数组。

2.分析做法

1.将当前序列一分为二,求出分裂点mid = (left + right) / 2;
2.对子序列arr[left,mid]递归,进行归并排序,结果放入data[left,mid]中;
3.对子序列arr[mid+1,right]递归,进行归并排序,结果放入data[mid+1,right]中;
4.调用算法merge,将有序的两个子序列归并成一个有序的序列data[left,right]。

3.代码实现

1. 实现方法一
public int[] mergeSort(int[] arr){

    sort(arr,0,arr.length - 1);
    return arr;
}

public void sort(int[] arr,int left,int right){

    if(left >= right)
    return;

    //将当前序列一分为二,求出分裂点mid
    int mid = (left + right) / 2;
    //二路归并排序里面有两个Sort,多路归并排序里面写多个Sort就可以了
    sort(arr,left,mid);
    sort(arr,mid+1,right);
    //左右归并
    merge(arr,left,mid,right);
}

private void merge(int[] arr,int left,int mid,int right){

    int[] temps = new int[right - left + 1];
    //左指针
    int i = left;
    //右指针
    int j = mid + 1;
    int k = 0;
    // 把较小的数先移到新数组中
    while (i <= mid && j <= right){
        if(arr[i] < arr[j]){
            temps[k++] = arr[i++];
        }else{
            temps[k++] = arr[j++];
        }
    }
    // 把左边剩余的数移入数组
    while (i <= mid){
        temps[k++] = arr[i++];
    }
    // 把右边边剩余的数移入数组
    while (j <= right){
        temps[k++] = arr[j++];
    }
    System.out.println("第"+(++number)+"趟排序:\t");
    //从临时数组拷贝到原数组
    for (int l = 0; l < temps.length; l++) {
        arr[left + l] = temps[l];
        //输出中间归并排序结果
        System.out.print(arr[left + l]+"\t");
    }
    System.out.println();
}
2. 实现方式二 实现思想和上面一样
private void mergeSort(int[] arr, int l, int r) {
    if(l >= r)
        return;
    int mid = (r + l) / 2;
    mergeSort(arr,l,mid);
    mergeSort(arr,mid + 1,r);
    merge(arr, l, mid, r);
}

private void merge(int[] arr, int l, int mid, int r) {

    //创建一个临时数组 大小为arr的长度
    int[] temp = new int[ r - l + 1];
    //arr中的数组赋值给临时数组
    for (int i = l; i <= r; i++){
        temp[i - l] = arr[i];
    }

    //拆分成两半
    // l =< i <= mid i代表左边数组的第一个元素
    int i = l;
    // mid+1 =< j <= r  j代表右边数组的第一个元素
    int j = mid + 1;
    for (int k = l; k <= r; k++) {
        if(i > mid){
            //如果i > mid边界值了 则遍历右边数组
            arr[k] = temp[j - l];
            j++;
        }else if(j > r){
            //如果j > r边界值了 则遍历左边数组
            arr[k] = temp[i - l];
            i++;
        }else if(temp[i - l] > temp[j - l]){
            //arr[i] > arr[j]  arr[k] = arr[j]
            arr[k] = temp[j - l];
            j++;
        }else{
            //否则arr[k] = arr[i]
            arr[k] = temp[i-l];
            i++;
        }
    }
}

4.测试

@Test
public void test(){
    int arr[] = {0,1,1,2,3,3,4,8,7,6,12,22,65};
    //int arr[] = {6,3,8,2,9,1};
    System.out.println("排序前");
    printArr(arr);
    int[] data = mergeSort(arr);
    System.out.println("排序后");
    printArr(data);
}

public void printArr(int[] arr){
    for (int i = 0; i < arr.length; i++) {
        System.out.print(arr[i]+" ");
    }
    System.out.println();
}

5.总结

归并排序是稳定排序,
可用于链式结构,且不需要附加存储空间,但递归实现时仍需要开辟相应的递归工作栈。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值