基于分治的思想,首先在数组中选择一个基准点,选取基准点的效率决定了时间复杂度,从数组两端扫描数组,设置 lowhigh 两个索引,图中蓝标代表 low 红标代表 high ,橘色表代表重合位置

首次分割,数列被分成了两个子数列,长度分别是 i-1n-i ,排序时间表示为 T(i-1)T(n-i) ,计算总时间还得加上分割操作的时间,分割操作只用了循环 while(low<high) ,此段时间记为 cn ,所以 Tn = T(i-1)+T(n-i)+cn

# 演示

public class quicksort {
    public static void main(String[] args) {
        int[] arr = { 23, 46, 0, 8, 11, 18 };
        quickSort(arr, 0, arr.length - 1);
        System.out.print("排序后 ");
        for (int i : arr) {
            System.out.print(i+" ");
        }
    }
    private static void quickSort(int[] arr, int low, int high) {
        if (low < high) {
            // 找寻基准数据的正确索引
            int index = getIndex(arr, low, high);
            // 进行迭代对 index 之前和之后的数组进行相同的操作使整个数组变成有序
            //quickSort (arr, 0, index - 1); 之前的版本,这种姿势有很大的性能问题,谢谢大家的建议
            quickSort(arr, low, index - 1);
            quickSort(arr, index + 1, high);
        }
    }
    private static int getIndex(int[] arr, int low, int high) {
        // 基准数据
        int tmp = arr[low];
        while (low < high) {
            // 当队尾的元素大于等于基准数据时,向前挪动 high 指针
            while (low < high && arr[high] >= tmp) {
                high--;
            }
            // 如果队尾元素小于 tmp 了,需要将其赋值给 low
            arr[low] = arr[high];
            // 当队首元素小于等于 tmp 时,向前挪动 low 指针
            while (low < high && arr[low] <= tmp) {
                low++;
            }
            // 当队首元素大于 tmp 时,需要将其赋值给 high
            arr[high] = arr[low];
        }
        // 跳出循环时 low 和 high 相等,此时的 low 或 high 就是 tmp 的正确索引位置
        // 由原理部分可以很清楚的知道 low 位置的值并不是 tmp, 所以需要将 tmp 赋值给 arr [low]
        arr[low] = tmp;
        return low; // 返回 tmp 的正确位置
    }
}

# 最坏的情况

数列每次分割得到的两个子数列长度为 n-10 ,也就是其中的每一个元素都要移动 n 次,总时间 T(n^2)

T(n)       =    T(n - 1)      +    C*n                    
T(n - 1)   =    T(n - 2)      +    C*(n - 1)      # 将 n 减 1,得到下个子序列
T(n - 2)   =    T(n - 3)      +    C*(n - 3)
....
T(2)       =    T(1)          +    C*2
T(1)       =    T(0)          +    C
# 将下一级表达式代入上一级
T(n) = T(0) + C*n + C*(n-1) + C*(n-2) + C*(n-3).....+C*(2)+C
# T(0)是等于0的
T(n) = C*n + C*(n-1) + C*(n-2) + C*(n-3).....+C*(2)+C
T(n) = C*[n + (n-1) + (n-2) + (n-3).....+2+1]T(n) = C*(n + 1)*n/2

最高阶为 n^2 ,最差时间复杂度为 O(n^2)

# 最好情况

数列每次分割得到的两个子数列长度等长,除分割时间以外左右各为 T(n/2) ,总时间 2T(n/2)+cn

T(n)       =    2T(n / 2)      +    C*n                    
T(n / 2)   =    2T(n / 4)      +    C*n / 2      
T(n / 4)   =    2T(n / 8)      +    C*n / 4 
....
# 将下一级表达式代入上一级,化简找到通项
T(n) = 2^k*T(n/2^k)+ kcn
# 当n/2^k->1, k = lg2n
T(n) = nT(1) + cnlg2n

最优时间复杂度为 O(nlgn)

# 平均时间复杂度

<<算法导论>> p98 p99