优先介绍时间复杂度为 $O(log(N))$ 的算法,其余 $O(n^2)$ 的直接复制粘贴在底部。

public class Note2_1_QuickSort {
    // 快速排序方法
    public static void quickSort(int[] q, int l, int r) {
        if (l >= r) return;
        // TODO 1 注意是 l - 1 和 r + 1 让下文从第一个数就开始比较
        int i = l - 1, j = r + 1;
        int x = q[(l + r) >> 1];
        while (i < j) {
            // TODO 2 不要弄反顺序
            do i++; while (q[i] < x);
            do j--; while (q[j] > x);
            if(i < j) swap(q, i, j);
        }
        // TODO 3 以 j 为基准
        quickSort(q, l, j);
        quickSort(q, j + 1, r);
    }
    // 交换数组中的两个元素
    private static void swap(int[] q, int i, int j) {
        int temp = q[i];
        q[i] = q[j];
        q[j] = temp;
    }
    public static void main(String[] args) {
        int[] arr = {1, -1, 3, 2};
        quickSort(arr,0, arr.length - 1);
        for (int item : arr) {
            System.out.println("item = " + item);
        }
    }
}
24.1.15更:这里会出现两个问题
while(q[i]<x);while(q[j]>x);为什么不能改为 while(q[i]<=x);while(q[j]>=x);?问题在于如果我们的基准x刚好取到最大/最小值,就会发生指针越界。
如数组4 2 1 5 3 , 第一轮迭代时 x = 1, q[i] = 4,q[j] = 1 但如果把等号加上,q[j] = 1 时就不会停下来,一直往左走直到越界。
quick_sort(q, l, j); quick_sort(q, j + 1, r);改成 quick_sort(q, l, i); quick_sort(q, i + 1, r);因为 l + r >> 1 是向下取整 , 如果 | l - j | = 1 , 那么 l + j >> 1 = l,那么递归到最后 j = l就是
quick_sort(q , l , l)就结束了, 不会死循环,如果用 i 做边界,x的取值还是q[l + r >> 1],
那最后 | i - l | = 1, quick_sort(q , l , i)执行完了 l 和 i 的值还没变,还是quick_sort(q , l , i),就死循环了。
换种说法就是,每次快排,数据范围都得改变(缩小)直到 缩到一个数,避免缩小到两个数的时候 ,数据范围不变,一直是那两个数,所以就得选用合适的边界:
所以到最后我们只需要记住两件事: