Java常用算法 - 快速排序

125 阅读3分钟

快速排序

原理

  1. 从数组中挑出1个元素,作为基准数。
  2. 将元素分而治之,小的移动至基准数左侧,大的移动至基准数右侧。
  3. 基准数两侧作为两个子数组,分别重复上述步骤。

图解分析

假设当前存在数组{12,23,67,2,34},需要对其进行快速排序,步骤如下所示:

  1. 先取数组第1个元素作为基准数,并声明指针I指向数组头部,指针J指向数组尾部。

  2. 从右往左移动指针J,找出第1个小于基准数的值。

QuickSort1.jpg

  1. 从左往右移动指针I,找出第1个大于基准数的值,并将其与指针J所指数值进行交换。

QuickSort2.jpg

  1. 交换后,按照1、2步骤依次移动指针J和指针I。

    若指针IJ重叠时,则移动结束,此时将指针IJ共同指向元素与基准数进行交换。

QuickSort3.jpg

经过步骤4后,我们可以得到以下结果:基准数元素(指针IJ共同指向元素)将数组切分为2个子数组,左侧子数组的元素均小于基准数,右侧子数组的元素均大于基准数。

QuickSort4.jpg

接下来我们将切分出来的2个子数组分别重复1~4步骤,直到子数组无法再继续拆分(例如:左侧子数组仅剩1个元素,无法进行拆分),这样我们便完成了数组的排序。

代码实现

public class QuickSort {

    public static void sort(int[] arr, int low, int high) {

        // 跳出递归条件
        if (low >= high) {
            return;
        }

        int standard = arr[low]; // 基准数
        int i = low;
        int j = high;

        while (i < j) {

            // 从右往左, 筛选出小于基准数元素的位置
            while (standard <= arr[j] && i < j) {
                j--;
            }

            // 从左往右, 筛选出大于基准数元素的位置
            while (standard >= arr[i] && i < j) {
                i++;
            }

            // 交换位置
            if (i < j) {
                int temp = arr[j];
                arr[j] = arr[i];
                arr[i] = temp;
            }

        }

        // 左右指针重合, 基准数与ij重合的元素交按
        arr[low] = arr[i];
        arr[i] = standard;

        // 递归调用左半数组
        sort(arr, low, j - 1);

        // 递归调用右半数组
        sort(arr, j + 1, high);
    }

    public static void print(int[] arr) {
        System.out.print("排序结果: ");
        for (int item : arr) {
            System.out.print(item + " ");
        }
    }

    public static void main(String[] args) {
        int[] arr = new int[]{12, 23, 67, 2, 34};
        sort(arr, 0, arr.length - 1);
        print(arr);
    }
}

时间复杂度

最好情况

处理过程中的每个数组,基准数正好是数组的中位数,此时时间复杂度为:O(nlogn)。

最坏情况

操作过程中的每个数组,基准数正好是数组的最大值或者最小值。例如,我们需要对n个数进行排序,每进行处理的时候,选出的基准数均是数组的最小值。于是乎,在经过调换元素顺序的操作,最小值被放在第1位,以此类推,每次操作,都只能将最小值放到第1位,而剩下的元素,则没有任何变化,此时便等价于冒泡排序,时间复杂度为:O(n^2)。

参考文献

快速排序原理解析

冒泡排序与快速排序对比分析

快速排序时间复杂度分析