排序算法之快速排序

本文详细介绍了快速排序算法的工作原理,包括基础算法和步骤分析。通过实例展示了如何将序列分成较小和较大的子序列,使用递归进行排序。快速排序因其简单高效,在面试中常被考察,平均时间复杂度为O(n log n)。

快速排序作为应用最为广泛的算法,也是面试最常考的算法。快速排序流行的原因是因为,它是简单的,高效的,它的平均时间复杂度为O(nlogn),要比一般的排序算法更快O(n^2)

快速排序使用一种分治法(Divide and Conquer)将序列分为较小和较大的两个子序列,然后采用递归的形式进行排序。

快速排序基础算法

这是一个可以运行起来的快速排序代码。

public static void sort([] a) {
    sort(a, 0, a.length - 1);
}

private static void sort(Integer[] a, int lo, int hi) {
    if (hi <= lo) return;
    int j = partition(a, lo, hi);
    sort(a, lo, j-1);
    sort(a, j+1, hi);
}

private static int partition(Integer[] a, int lo, int hi) {

    // 将数组切分为 a[lo, i-1], a[i], a[i+1, hi]
    int i = lo, j = hi+1;
    Integer v = a[lo];
    while (true) {
        while (less(a[++i], v)) {  // 从左往右比较
            if (i==hi) {
               break;
            }
        }

       while (less(v, a[--j])) {  // 从右往左比较
            if (j==lo) {
               break;
            }
        }

        if (i >= j) {
            break;
        }
        exch(a, i, j);    // 交换
    }
    exch(a, lo, j);
    return j;
}

private static void exch(Integer[] a, int i, int j) {
    Integer temp = a[i];
    a[i] = a[j];
    a[j] = temp;
}

private static boolean less(Integer a, Integer b) {
    return a.compareTo(b) < 0;
}

算法步骤分析

假设对列表 6, 1, 2, 7, 9, 3, 4, 5, 10, 8 进行排序,第一步,以6为哨兵,对 1, 2, 7, 9, 3, 4, 5, 10, 8 进行操作。

分别有两个指针iji从左往右走,遇到比6大的数字停下;j从右往左走,遇到比6小的数字停下,然后进行交换。

得到:

1, 2, 5, 4, 3, 9, 7, 10, 8

此时,ij3的位置相遇,此位置也就是6排序后所在的位置,因此进行交换,得到:

3, 1, 2, 5, 4, 6, 9, 7, 10, 8

到此,可以将列表分为三部分,分别是3, 1, 2, 5, 469, 7, 10, 8

下面通过递归的方式,分别对子序列3, 1, 2, 5, 49, 7, 10, 8 进行快速排序。

  • 左子序列排序

分别有两个指针iji从左往右走,遇到比3大的数字停下;j从右往左走,遇到比3小的数字停下,然后进行交换。

结果发现,直到i, j相遇,也没有进行交换,此时j已经比i小,结束遍历,并将j所指向的值与基数3进行交换,得到 2, 1, 3, 5, 4

到此,可以将列表分为三部分,分别是2, 135, 4

分别对子序列2, 15, 4排序,得到

1, 24, 5

至此,左子序列排序完成,得到1,2,3,4,5

  • 右子序列排序

分别有两个指针iji从左往右走,遇到比9大的数字停下;j从右往左走,遇到比9小的数字停下,然后进行交换。

i遇到10停下,j遇到8停下,然后进行交换,得到 9, 7, 8, 10

j继续往前走,发现ij相遇,然后与基数9进行交换,得到 8, 7, 9, 10

到此,可以将列表分为三部分,分别是8, 7910

再对8, 7 进行排序,得到 7, 8

至此,右子序列排序完成,得到 7, 8, 9, 10

最后,整个序列的排序工作完成,得到:

1, 2, 3, 4, 5, 6, 7, 8, 9, 10

总结

快速排序的核心是如何做好切分,一般会选择列表的第一个元素作为基数比较,指定两个指针分别从前往后和从后往前进行遍历比较,直到指针相遇或者交错以后,遍历结束。

Refrence

  1. 《算法》第4版
  2. https://zh.wikipedia.org/wiki/快速排序
  3. https://wiki.jikexueyuan.com/project/easy-learn-algorithm/fast-sort.html
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值