排序算法-归并,快速,堆排序

归并排序

算法原理(从小到大为例):

  1. 将数组分成两部分,每部分分别排序,形成有序的两部分,然后遍历比较每部分的头部元素,形成新的数组
  2. 其中,每部分分别排序,递归使用步骤1,递归终止情况为:需要排序的部分只有一个元素

在这里插入图片描述
图片来源:极客时间,《数据结构与算法之美》,12章

时间复杂度:O(n*log(n)),空间复杂度:O(n) ,稳定的排序算法
java代码

/**
     * 从小到大排序
     * @param nums
     */
    public static void mergeSort(int[] nums){
        int[] tmp = new int[nums.length];//作为中间数组,可以重复利用
        mergeSort(nums,0,nums.length-1,tmp);
    }

    /**
     *
     * @param nums
     * @param start 排序的左边界,包含
     * @param end 排序的右边界,包含
     */
    private static void mergeSort(int[] nums,int start,int end,int[] tmp){
        if(start >= end){
            return;
        }
        int mid = (start+end)/2;
        mergeSort(nums,start,mid,tmp);
        mergeSort(nums,mid+1,end,tmp);
        merge(nums,start,mid,mid+1,end,tmp);
    }

    private static void merge(int[] nums,int s1,int e1,int s2,int e2,int[] tmp){
        int index=0;
        int ts1=s1,ts2=s2;
        while (ts1<=e1 && ts2<=e2){
            if(nums[ts1]<=nums[ts2]){
                tmp[index++] = nums[ts1++];
            }else{
                tmp[index++] = nums[ts2++];
            }
        }
        while (ts1<=e1){
            tmp[index++] = nums[ts1++];
        }
        while (ts2<=e2){
            tmp[index++] = nums[ts2++];
        }
        for(int i=0;i<index;i++){
            nums[s1++]=tmp[i];//因为算法保证了传入的s1,e1,s2,e2是连续的,所以这里直接从tmp中复制过来即可,不存在中间空洞数据被覆盖的情况
        }
    }

快速排序

算法原理(从小到大排序):

  1. 从数组中选择一个基准元素,通过分割算法遍历数组,使得基准元素左边都是比基准元素小的,右边都是比基准元素大的,然后递归快排左右两部分
  2. 分割算法:两个索引下标分别指向数组低位与高位,low,high;low从左侧开始遍历直至碰见第一个比基准元素大的,然后high从右边开始遍历,直至碰见第一个比基准元素小的,交换两个元素,继续遍历,直至low==high

时间复杂度:O(n*log(n)),空间复杂度:O(n),是不稳定排序
java代码如下:

/**
     * 从小到大排序
     * @param nums
     */
    public static void quickSort(int[] nums){
        quickSort(nums,0,nums.length-1);
    }

    /**
     *
     * @param nums
     * @param low
     * @param high
     */
    private static void quickSort(int[] nums,int low,int high){
        if(low<high){
            int index = partition(nums,low,high);
            quickSort(nums,low,index);
            quickSort(nums,index+1,high);
        }
    }

    /**
     * 选择中间元素为基准元素
     * @param nums
     * @param low 边界,包含
     * @param high 边界,包含
     * @return 返回基准元素或后一位的索引下标,返回后一位的情况只可能是
     */
    private static int partition(int[] nums,int low,int high){
        int pivot = nums[(low+high)/2];
        while (true){
            while (nums[low]<pivot) low++;//这里不能加上=条件,否则有可能low就越过基准元素了
            while (nums[high]>pivot) high--;//同理这里不能加上=条件
            if(low>=high){
                return high;//要么是相邻交换最终high<low;要么是指向同一个元素,其中一边移动,最终还是high<low,所以high才是最终的分割线
            }
            //未越界的情况下交换
            swap(nums,low++,high--);
        }
    }

堆排序

参考:排序算法-堆排序

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值