快速排序

本文深入解析了快速排序算法的原理及实现,介绍了Lomuto和Hoare两种分区方案,提供了详细的伪代码示例,并讨论了pivot的选择策略及重复元素的处理方法。

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

排序算法 —— 快速排序(quick sort)

推荐可视化网页visualgo, sorting.at, usfca, youtube.

快速排序算法分三步:

  1. 取pivot,并将数组分成大于pivot和小于pivot两部分,并且小于pivot的部分在pivot左边,大于的在右边。
  2. 对每边分别进行快速排序(递归)。
  3. 将排序好的部分合起来。
Lomuto partition scheme

每次取最左边一个数作为pivot。

public void quickSort(int[] nums) {
    quickSortHelper(nums, 0, nums.length - 1);
}

private void quickSortHelper(int[] nums, int head, int tail) {
    if (head < tail) {
        int threshold = findThreshold(nums, head, tail);
        quickSortHelper(nums, head, threshold - 1);
        quickSortHelper(nums, threshold + 1, tail);
    }
}

private int findThreshold(int[] nums, int head, int tail) {
    int pivot = head;
    int index = head + 1;
    for (int i = index; i <= tail; i++) {
        if (nums[i] < nums[pivot]) {
            swap(nums, i, index);
            index++;
        }
    }
    swap(nums, pivot, index - 1);
    return index - 1;
}

private void swap(int[] arr, int i, int j) {
    int tmp = arr[i];
    arr[i] = arr[j];
    

实际上findThreshold中的循环可以用两个指针进行:

private int findThreshold(int[] nums, int head, int tail) {
    int pivot = head;
    int i = head + 1;
    int j = tail;
    while (i < j) {
        while (nums[i] < nums[pivot]) {
            i++;
        }
        while (nums[j] > nums[pivot]) {
            j--;
        }
        if (i < j) swap(nums, i, j);
    }
    swap(nums, pivot, j);
    return j;
}
Hoare partition scheme

取数组中间数作为pivot,用两个指针,一个指向开头,另一个指向结尾,彼此靠近,直到位于数组中的一对元素,一个大于pivot,一个小于pivot,则对这两个元素进行交换。

algorithm quicksort(A, lo, hi) is
    if lo < hi then
        p := partition(A, lo, hi)
        quicksort(A, lo, p)
        quicksort(A, p + 1, hi)

algorithm partition(A, lo, hi) is
    pivot := A[(hi + lo) / 2]
    i := lo - 1
    j := hi + 1
    loop forever
        do
            i := i + 1
        while A[i] < pivot
        do
            j := j - 1
        while A[j] > pivot
        if i ≥ j then
            return j
        swap A[i] with A[j]

本身的Hoare partition scheme算法不能解决元素重复问题,因此要做改进。

  1. 对pivot选择:
mid := (lo + hi) / 2
if A[mid] < A[lo]
    swap A[lo] with A[mid]
if A[hi] < A[lo]
    swap A[lo] with A[hi]
if A[mid] < A[hi]
    swap A[mid] with A[hi]
pivot := A[hi]
  1. 重复问题:
algorithm quicksort(A, lo, hi) is
    if lo < hi then
        p := pivot(A, lo, hi)
        left, right := partition(A, p, lo, hi)  // note: multiple return values
        quicksort(A, lo, left - 1)
        quicksort(A, right + 1, hi)

reference:wiki-quickSort

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值