常用的排序02(归并排序、快速排序)

博客介绍了归并排序和快速排序两种算法。归并排序将数组分成两部分分别排序后合并,空间复杂度 O(n),时间复杂度 O(nlogn),是稳定排序。快速排序选分区点,将数据分区后递归排序,空间复杂度 O(1),最好时间复杂度 O(nlogn),最坏 O(n^2),是非稳定排序。还对比了两者处理过程和内存占用情况。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、归并排序

排序思路:把数组从中间分成前后两部分,然后对前后两部分分别排序,再将排好序的两部分合并在一起,这样整个数组就都有序了。

举例:

实现代码:

public class MergeSort{

    public static void sort(int[] arr) {
        int len = arr.length;
         //使用递归实现
        sort(arr, 0, len - 1);
    }

    /**
     * 递归终止条件
     * if p >= r  then return
     * 取p到r之间的中间位置q
     * q = (p+r) / 2
     * 分治递归
     * merge_sort_c(A, p, q)
     * merge_sort_c(A, q+1, r)
     * 将A[p...q]和A[q+1...r]合并为A[p...r]
     * merge(A[p...r], A[p...q], A[q+1...r])}
     *
     * @param arr
     * @param p
     * @param r
     */
    public static void sort(int[] arr, int p, int r) {
        if (p >= r) {
            return;
        }
        int q = (p + r) / 2;
        sort(arr, p, q);
        sort(arr, q + 1, r);
        int[] tempArr = new int[r - p + 1];
        int k = 0;
        int i = p;
        int j = q + 1;
        while (i <= q && j <= r) {
            //= 一定要加,稳定排序
            if (arr[i] <= arr[j]) {
                tempArr[k++] = arr[i++];
            } else {
                tempArr[k++] = arr[j++];
            }
        }
        if (i <= q) {
            for (; i <= q; i++) {
                tempArr[k++] = arr[i];
            }
        } else if (j <= r) {
            for (; j <= r; j++) {
                tempArr[k++] = arr[j];
            }
        }
        for (int l = p; l <= r; l++) {
            arr[l] = tempArr[l - p];
        }
    }

    public static void main(String[] args) {
        int[] arr = {3, 1, 2, 4, 5, 6, 8, 7};
        sort(arr);
        Console.log(Arrays.toString(arr));
    }
}

复杂度:

​1、空间复杂度为 O(n),非原地排序算法。
2、时间复杂度为 O(nlogn)。最好 最坏都为 O(nlogn)
3、稳定的排序算法。

2、快速排序

排序思路:如果要排序数组中下标从 p 到 r 之间的一组数据,我们选择 p 到 r 之间的任意一个数据作为 pivot(分区点)。遍历 p 到 r 之间的数据,将小于 pivot 的放到左边,将大于 pivot 的放到右边,将 pivot 放到中间。经过这一步骤之后,数组 p 到 r 之间的数据就被分成了三个部分,前面 p 到 q-1 之间都是小于 pivot 的,中间是 pivot,后面的 q+1 到 r 之间是大于 pivot 的。递归排序下标从 p 到 q-1 之间的数据和下标从 q+1 到 r 之间的数据,直到区间缩小为 1,就说明所有的数据都有序了。

举例:

实现代码:

public class QuickSort{

    public static void sort(int[] arr) {
        int len = arr.length;
        quickSort(arr, 0, len - 1);
    }

    public static void quickSort(int[] arr, int p, int r) {
        if (p >= r) {
            return;
        }
        int val = arr[r];
        int i = p;
        for (int j = p; j <= r; j++) {
            if (arr[j] < val) {
                int temp = arr[j];
                arr[j] = arr[i];
                arr[i] = temp;
                i++;
            }
        }
        arr[r] = arr[i];
        arr[i] = val;
        int q = i;
        quickSort(arr, p, q - 1);
        quickSort(arr, q + 1, r);
    }

    public static void main(String[] args) {
        int[] arr = {3, 1, 2, 4, 5, 6, 8, 7};
        sort(arr);
        Console.log(Arrays.toString(arr));
    }
}

复杂度:

1、空间复杂度为 O(1),原地排序算法。
2、时间复杂度为 O(nlogn)。分割点均分数据,最好 O(nlogn) 最坏为 O(n^2)
3、非稳定的排序算法。

3、两者对比

两种排序都是利用分治的思想,两者的区别:归并排序的处理过程是由下到上的,先处理子问题,然后再合并。而快排正好相反,它的处理过程是由上到下的,先分区,然后再处理子问题。归并排序虽然是稳定的、时间复杂度为 O(nlogn) 的排序算法,但是它是非原地排序算法。快速排序通过设计巧妙的原地分区函数,可以实现原地排序,解决了归并排序占用太多内存的问题。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值