归并排序与快速排序


title: 归并排序与快速排序
date: 2020-03-04 17:21:53
categories:

  • 数据结构与算法
    tags:
  • 排序

分治|递归思想

分治,即分而治之,将大的问题分割成小的问题,一一解决,有的问题需要汇总,有的并不需要。

归并:要排序一个数组,就是将这个数组,均分成两部分,然后继续对两部分进行均分至不能分割,最后将分割的各个部分排好序,组合起来。

递推公式:mergeSort(array , begin , end) = merge(mergeSort(array , begin , mid) + mergeSort(array , mid + 1 , end))

代码实现:

public class Merge {
    public void mergeSort(int[] a , int begin , int end){
        if(begin >= end){
            return;
        }
        int mid = (begin + end) / 2;
        mergeSort(a , begin , mid);
        mergeSort(a , mid + 1 , end);
        merge(a , begin, end , mid);
    }
    //merge函数,将前后两部分(相当于两个数组)进行组合,新开辟一个数组空间,遍历比较两个子数组,
    public void merge(int[] a , int begin , int end , int mid){
        int i = begin;
        int j = mid + 1;
        int k = 0;
        int[] tmp = new int[a.length];
        while(i <= mid && j <= end){
            if(a[i] <= a[j]){
                tmp[k++] = a[i++];
            }else{
                tmp[k++] = a[j++];
            }
        }
        while(i <= mid){
            tmp[k++] = a[i++];
        }
        while(j <= end){
            tmp[k++] = a[j++];
        }
        for (int l = 0; l <= end - begin; l++) {
            a[begin + l] = tmp[l];
        }
    }

    public static void main(String[] args) {
        Merge merge = new Merge();
        int[] a = {1 , 4, 3, 5 ,2};
        merge.mergeSort(a , 0 , a.length - 1);
        for (int i = 0; i < a.length; i++) {
            System.out.println(a[i]);
        }
    }

}

快排:与归并排序均分不同,快排十要先找一个分区点,将比分区点小的元素排在分区点之前,大的排在分区点之后,根据分区点,将数组分割为前后两个部分,对这两部分重复进行分区操作,直至区间为1为止。

递推公式:quickSort(array , begin , end) = quickSort(array , begin , partition - 1) + quickSort(array , partition + 1 , end)

代码实现:

public class Quick {
    public void qucikSort(int[] array , int begin , int end){
        if(begin >= end) return;
        int p = partition(array , begin , end);
        //分成三部分,begin->(p-1),分区点p,(p+1)->end。
        qucikSort(array , begin , p - 1);
        qucikSort(array , p + 1 , end);

    }
    //区分点取末尾元素
    //处理操作:将小的置于分区点左边,大的置于分区点右边。
    //通过游标i将数组分为*已处理区间(全为小于等于区分点的元素)*和*未处理区间*,将循环元素与分区点比较,若小,就将元素通过交换加入到已处理区间末尾,即array[i]元素。
    //最后,将区分点与处理区间划分点a[i]交换
    public int partition(int[] array , int begin , int end){
        int i = begin;
        int pivot = array[end];
        int k = i;
        for (; k < end ; k++) {
            if(array[k] <= pivot){
                swap(array , i , k);
                i++;
            }
        }
        swap(array , i , end);
        return i;
    }
    public void swap(int[] a , int i , int j){
        int tmp = a[j];
        a[j] = a[i];
        a[i] = tmp;
    }
    public static void main(String[] args) {
        Quick quick = new Quick();
        int[] a = {1 , 4, 3};
        quick.quickSort(a , 0 , a.length - 1);

        for (int i = 0; i < a.length; i++) {
            System.out.println(a[i]);
        }
    }
}

区别

归并排序,可以看成是自下而上的,先处理子问题,然后将各个部分组合起来;快速排序,可以看成是自上而下的,先进行分区,再处理子问题。

归并排序在merge时,需要开辟新的内存空间,不是原地排序算法。

快排在分区时,需要交换元素,不是稳定的排序算法。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值