vlambda博客
学习文章列表

这个排序真的猛,难怪叫快速排序!

  • 简介

    快速排序是一种 O(logn) 时间复杂度的排序,它的基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。【来自百度百科】

  • 解析

    1. 首先给定一个数组 arr = { 5,8,7,3,4,9 },此时需要排序的位置为左边 left = 0 , 右边为 right = 5

    2. 选择第一个数为基准数记为 pivot = 5,此时 left = 0

    3. 开始从后面找比基准数小的数

      1. right = 5 此时 arr[5] = 9 > pivot 不满足 right--

      2. right = 4 此时 arr[4] = 4 < pivot 满足

      3. 然后把 arr[4] 的值填入 arr[left] 也就是 arr[0] 中,此时数组为  4 8 7 3 4 9

    4. 开始从前面找比基准数大的数字

      1.  left = 0 此时 arr[0] = 5 == pivot 不满足 left++

      2.  left = 1 此时 arr[1] = 8 满足

      3.  然后把 arr[1] 的值填入 arr[right]也就是 arr[4]中,此时数组为 4 8 7 3 8 9

    5. 重复步骤3,right = 3 时,与left = 1 交换得到数组为 4 3 7 4 8 9

    6. 重复步骤4,left = 2 时,与right = 3 交换得到数组为 4 3 4 7 8 9

    7. 重复步骤3,此时 right = 2 与 left = 2 相同,则说明比较结束,将 pivot放入right的位置,即 arr[2] = 5 数组为 4 3 5 7 8 9

    8. 此时pivot左边均比5小,右边均比5大,完成对这个数的排序

    9. 接下来递归 [0,right-1]序列和[right-1,arr.length]序列完成所有排序

  • 代码示例


    package com.wangp.myaop.coding;
    import java.util.Arrays;import java.util.Random;import org.apache.http.util.Asserts;
    /** * @author tooStrongerW * @version 1.0 * @date 2021/3/30 21:16 */public class QuickSort {
    public static void main(String[] args) { // 指定数组大小 int capacity = 10_000; // 生成随机数组 int[] arr = genRandomArr(capacity); // 排序 quickSort(arr); // 断言数组顺序 checkArrOrder(arr); } private static void quickSort(int[] arr) { quickSort(arr, 0, arr.length - 1); }
    private static void quickSort(int[] arr, int left, int right) { // 递归退出条件 if (left >= right) { return; } // 选取基准数 int pivot = arr[left]; int start = left; int end = right; // 开始比较 while (start < end) { // 当 start 小于 end 并且后面的值大于或等于基准值的时候,后面指针向前移动 while (start < end && arr[end] >= pivot) { end--; } // 填空 if (start < end) { arr[start] = arr[end]; } // 当 start 小于 end 并且前面面的值小于或等于基准值的时候,前面指针向后移动 while (start < end && arr[start] <= pivot) { start++; } // 填空 if (start < end) { arr[end] = arr[start]; } // 比较完成,让基准数回到它该到的位置 if (start >= end) { arr[start] = pivot; } } // 相同方式排序左子序列 quickSort(arr, left, end - 1); // 相同方式排序右子序列 quickSort(arr, end + 1, right); }
    private static int[] genRandomArr(int capacity) { int[] arr = new int[capacity]; Random random = new Random(); for (int i = 0; i < capacity; i++) { int num = random.nextInt(capacity); arr[i] = num; } return arr; }
    private static void checkArrOrder(int[] arr) { for (int i = 0; i < arr.length - 1; i++) { Asserts.check(arr[i] <= arr[i + 1], "未排好序!"); } }}
  • 小结

    1. 快速排序选择基准数时,尽量范围内随机选择,为了解释方便才使用第一个做基准数

    2. 由于用到了递归,一定要判定递归结束条件