排序问题—归并排序

特点

归并排序适用于外部排序(存在磁盘上)也适用于链表排序。
希尔排序,堆排序,快速排序都依赖于数组的随机访问能力,不适用于链表排序。

思路

核心思路:合并两个有序数组,采用分治的思想。(思路都在代码上)
在这里插入图片描述
在这里插入图片描述

代码

package sort;

import java.util.Arrays;

public class mergeSort {
    //归并排序
    //h核心思想是合并两个有序数组
    public static void mergeSort(int []array){
        //为了代码简单,将区间设置为前闭后开
        mergeSorthelper(array,0,array.length);
    }


    //借助辅助方法实现递归多区间排序
    private static void mergeSorthelper(int[] array,int low,int hight) {
        //此时是一个前闭后开区间[low,hight)
        // 当她两差值<=1时,代表该区间最多只有一个元素,不需要排序,作为递归结束的条件
        if (hight-low<=1){
            return;
        }
        //将整个区间均分为两份,[low,mid),[mid,hight)
        int mid=(low+hight)/2;
        //递归操作每个被区分的小区间,直到区间中最多只有一个元素,递归结束
        //这个方法递归完,表示[low,mid)以排序完
        mergeSorthelper(array,low,mid);
        //这个方法递归完,表示[mid,hight)以排序完
        mergeSorthelper(array,mid,hight);
        //当每个小区间都有序时,接下来进行合并有序区间操作,传两个区间过去
        merge(array,low,mid,hight);
    }


     //进行合并有序区间操作,两个有序区间就是[low,mid),[mid,hight)
    private static void merge(int[] array, int low, int mid, int hight) {
        //先将下标备份记录下来
        int i=low;
        int j=mid;
        //开辟一个新数组用来存放临时比较操作
        int [] temp=new int[hight-low];
        int k=0;//k表示新数组下标
        //同时从两个区间的头部(low,mid)出发,谁小就先存放到新数组中去,
        // 若一区间以全部比较完,就将另一个区间的值全部尾插进新数组
        while (i<mid&&j<hight){
            //这里的<=是为了保证稳定性
            if (array[i]<=array[j]){
                temp[k]=array[i];
                //更新i,k,往前走
                i++;
                k++;
            }
            else {
                temp[k]=array[j];
                k++;
                j++;

            }
        }
        //上述循环结束,则一定代表i走到尽头,或者j走到尽头,此时将另一个区间剩下的元素入新数组即可
        //因为区间内本身是有序数组,所以直接入新数组不会有问题
        while (i<mid){
            temp[k] = array[i];
            i++;
            k++;
        }
        while (j<hight){
            temp[k] = array[j];
            j++;
            k++;
        }
        //此时新数组中就是一组已经合并了的有序数组,将新数组循环遍历搬运至旧数组
        for (int p = 0;p < hight-low;p++){
          array[low+p]=temp[p];
        }
    }
    
     public static void main(String[] args){
        int [] array={9,3,8,1,0,0,5,9,2,6};
        mergeSort(array);
        System.out.println(Arrays.toString(array));
    }
}

性能

时间复杂度:O(n*log(n));
空间复杂度:O(n)+O(logN)=O(n);
空间复杂度中,O(n)是因为因开辟了新数组,O(logN
)是因为递归时栈占用的空间,总体看就是O(N);
当归并排序针对链表进行排序时,空间复杂度是O(1);
稳定性:稳定。

非递归版本代码

package sort;

import java.util.Arrays;

public class mergeSort {

public static void mergeSortByLoop(int[] array){
        for (int i=1;i<array.length;i=i*2){//引入一个i变量进行分组
            //下面的循环执行一次就完成了一次相邻两个组的合并
            for (int j = 0;j<array.length;j=j+2*i){
                int beg=j;
                int mid=j+i;
                int end=j+2*i;
                if (mid>array.length){
                    mid=array.length;
                }
                if (end>array.length){
                    end=array.length;
                }
                merge(array,beg,mid,end);
            }
        }
    }

 //进行合并有序区间操作,两个有序区间就是[low,mid),[mid,hight)
    private static void merge(int[] array, int low, int mid, int hight) {
        //先将下标备份记录下来
        int i=low;
        int j=mid;
        //开辟一个新数组用来存放临时比较操作
        int [] temp=new int[hight-low];
        int k=0;//k表示新数组下标
        //同时从两个区间的头部(low,mid)出发,谁小就先存放到新数组中去,
        // 若一区间以全部比较完,就将另一个区间的值全部尾插进新数组
        while (i<mid&&j<hight){
            //这里的<=是为了保证稳定性
            if (array[i]<=array[j]){
                temp[k]=array[i];
                //更新i,k,往前走
                i++;
                k++;
            }
            else {
                temp[k]=array[j];
                k++;
                j++;

            }
        }
        //上述循环结束,则一定代表i走到尽头,或者j走到尽头,此时将另一个区间剩下的元素入新数组即可
        //因为区间内本身是有序数组,所以直接入新数组不会有问题
        while (i<mid){
            temp[k] = array[i];
            i++;
            k++;
        }
        while (j<hight){
            temp[k] = array[j];
            j++;
            k++;
        }
        //此时新数组中就是一组已经合并了的有序数组,将新数组循环遍历搬运至旧数组
        for (int p = 0;p < hight-low;p++){
          array[low+p]=temp[p];
        }
    }


    public static void main(String[] args){
        int [] array={9,3,8,1,0,0,5,9,2,6};
        mergeSortByLoop(array);
        System.out.println(Arrays.toString(array));
    }
}

海量数据排序问题

在这里插入图片描述

排序总结

面试常考:背过!
在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值