宝藏速成秘籍(1)快速排序法

一、前言

       快速排序(Quicksort)是一种高效的排序算法,最早由Tony Hoare在1960年提出。它采用了分治的策略,通过递归地将数组分为较小的部分来排序。

1.1、概念

        快速排序(Quicksort)的基本思想是通过一轮排序将待排序数组划分为独立的两部分,其中一部分的所有元素都比另一部分的所有元素小,然后递归地对这两部分进行排序。快速排序的关键在于如何选择“枢轴”(Pivot)以及如何进行分区。

1.2、排序步骤

  1.选择枢轴:从数组中选择一个元素作为枢轴(通常是最后一个元素、随机选择的元素或中间的元素)。
  2.分区:重排数组,使得枢轴左边的所有元素小于等于枢轴,枢轴右边的所有元素大于枢轴。分区结束后,枢轴元素位于其最终位置。
  3.递归排序:递归地对枢轴左右两部分的子数组进行快速排序。

二、方法分析

假设选择数组的最后一个元素作为枢轴,分区过程如下:

1. 初始化两个指针:`i`和`j`,其中`i`表示小于等于枢轴的最后一个元素的位置,`j`表示当前扫描的元素位置。
2. 从左到右扫描数组,若当前元素小于等于枢轴,则将其与`i`位置的元素交换,并将`i`向右移动一位。
3. 扫描完所有元素后,将枢轴元素与`i+1`位置的元素交换,完成分区。

三、举例说明

假设对数组`[10, 7, 8, 9, 1, 5]`进行快速排序,选择最后一个元素`5`作为枢轴:

1. 初始状态:`[10, 7, 8, 9, 1, 5]`
2. 分区过程:将小于等于`5`的元素移到左边,大于`5`的元素移到右边,得到`[1, 7, 8, 9, 10, 5]`,交换`5`和`7`得到`[1, 5, 8, 9, 10, 7]`,此时`5`在正确位置。
3. 递归排序左子数组`[1]`和右子数组`[8, 9, 10, 7]`。

通过上述步骤,数组最终排序完成。

四、编码实现

以下是Java实现快速排序的代码:

public class QuickSort {

    // 主方法,测试快速排序
    public static void main(String[] args) {
        int[] arr = {10, 7, 8, 9, 1, 5};
        int n = arr.length;
        
        QuickSort ob = new QuickSort();
        ob.quickSort(arr, 0, n - 1);
        
        System.out.println("排序后的数组:");
        printArray(arr);
    }

    // 快速排序方法
    void quickSort(int[] arr, int low, int high) {
        if (low < high) {
            // pi是分区索引,arr[pi]已经排好序
            int pi = partition(arr, low, high);

            // 递归地对左侧和右侧的子数组进行排序
            quickSort(arr, low, pi - 1);
            quickSort(arr, pi + 1, high);
        }
    }

    // 分区方法
    int partition(int[] arr, int low, int high) {
        int pivot = arr[high];
        int i = (low - 1); // 较小元素的索引

        for (int j = low; j < high; j++) {
            // 如果当前元素小于或等于pivot
            if (arr[j] <= pivot) {
                i++;

                // 交换arr[i]和arr[j]
                int temp = arr[i];
                arr[i] = arr[j];
                arr[j] = temp;
            }
        }

        // 交换arr[i+1]和arr[high](或pivot)
        int temp = arr[i + 1];
        arr[i + 1] = arr[high];
        arr[high] = temp;

        return i + 1;
    }

    // 打印数组方法
    static void printArray(int[] arr) {
        int n = arr.length;
        for (int i = 0; i < n; ++i)
            System.out.print(arr[i] + " ");
        System.out.println();
    }
}

运行结果:

五、方法评价

5.1时间复杂度

        快速排序的时间复杂度在平均情况下是O(n log n),在最坏情况下是O(n²)。通过选择合适的枢轴,可以在很大程度上避免最坏情况,通常采用随机选择枢轴或“三点取中法”来优化枢轴的选择。

5.2优缺点

优点:
- 平均情况下性能很好,时间复杂度为O(n log n)。
- 原地排序算法,不需要额外的存储空间(除了递归调用栈)。

缺点:
- 最坏情况下时间复杂度为O(n²)。
- 不稳定排序算法(相同元素的相对顺序可能会改变)。

结语

天行健,君子以自强不息

相信自己,努力必会有所收获,大好前程在等着你

     !!!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值