排序算法(六):快速排序

一、排序原理

快速排序是对冒泡排序的一种改进。基本的思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的数据要小,然后按照此方法对这两部分的数据分别进行快速排序,排序过程递归进行,以此达到整个数据都变成有序序列。

具体的排序步骤如下:

  1. 首先设定一个分界值,通过该分界值将数组分成左右两部分。
  2. 将大于或等于分界值的数据放到数组右边,小于分界值的数据放到左边。此时,左边部分中各元素都小于或等于分界值,而右边部分中的各元素都大于或等于分界值。
  3. 然后,分界值左侧和右侧的数据又可以独立进行排序,排序方式同步骤2.
  4. 重复上述过程,即进行递归操作,当左侧和右侧的数据都排序好后,整个数组的排序也就完成了。

二、排序实现

import java.util.Arrays;

/**
 * 快速排序
 */
public class QuickSort {

    public static void main(String[] args) {
        Integer[] arr = {4, 5, 3, 9, 2, 1};
        sort(arr);
        System.out.println(Arrays.asList(arr).toString());
    }

    public static void sort(Comparable[] a) {
        int lo = 0;
        int hi = a.length - 1;
        sort(a, lo, hi);
    }

    public static void sort(Comparable[] a, int lo, int hi) {
        // 安全校验
        if (hi <= lo) {
            return;
        }
        // 需要对数组中lo索引到hi索引处的元素进行分组(分为:左子组和右子组)
        int partition = partition(a, lo, hi); // 返回的是分组的分界值所在的索引,即分界值变换后的索引
        // 让左子组有序
        sort(a, lo, partition - 1);
        // 让右子组有序
        sort(a, partition + 1, hi);

    }

    // 对数组a中,从索引lo到hi之间的元素进行分组,并返回分组界限所对应的索引
    private static int partition(Comparable[] a, int lo, int hi) {
        // 确定分界值
        Comparable key = a[lo];
        // 定义两个指针,分别指向待切分元素的最小索引处+1和最大索引处
        int left = lo;
        int right = hi + 1;
        while (true) {
            while (less(key, a[--right])) {
                if (right == lo) {
                    break;
                }
            }
            while (less(a[++left], key)) {
                if (left == hi) {
                    break;
                }
            }
            if (left >= right) {
                break;
            } else {
                exch(a, left, right);
            }
        }
        int cutoffIndex = right; // 也可以等于left(因为此时left和right是相等的)
        exch(a, lo, cutoffIndex);
        return cutoffIndex;
    }

    private static boolean less(Comparable i, Comparable j) {
        return i.compareTo(j) < 0;
    }

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

三、快速排序的时间复杂度

最优和平均情况:O(nlogn)

最坏情况:O(n^2)

 

posted @ 2020-05-27 10:38  灰色飘零  阅读(160)  评论(0)    收藏  举报