算法——快速排序

161 阅读2分钟

概念扫盲

稳定:如果a原本在b前面,而a=b,排序之后a仍然在b的前面;
不稳定:如果a原本在b的前面,而a=b,排序之后a可能会出现在b的后面;
内排序:所有排序操作都在内存中完成;
外排序:由于数据太大,因此把数据放在磁盘中,而排序通过磁盘和内存的数据传输才能进行;
时间复杂度: 一个算法执行所耗费的时间。
空间复杂度: 运行完一个程序所需内存的大小。

介绍

使用分治策略来把一个大数组分为两个小数组。
快速排序又是一种分而治之思想在排序算法上的典型应用。本质上来看,快速排序应该算是在冒泡排序基础上的递归分治法。

实现策略

1、从数列中挑出一个元素,称为 “基准”;

2、重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。在这个分区退出之后,该基准就处于数列的中间位置。这个称为分区操作;

3、递归地把小于基准值元素的子数组和大于基准值元素的子数组排序;

时间复杂度:

主要还是看数据规模
最好情况:时间复杂度为:O(n)

最坏情况:时间复杂度为:O(n²)

空间复杂度

O(n^2)

let a = 1;let b = 2;let c = 3; 上述代码的临时空间不会随着n的变化而变化,因此空间复杂度为O(1)
let arr []; for(i=1; i<=n; ++i){ arr.push(i);} 上述可以看到,随着n的增加,数组的占用的内存空间越大
通常来说,只要算法不涉及到动态分配的空间,以及递归、栈所需的空间
空间复杂度通常为O(1),一个一维数组a[n],空间复杂度O(n),二维数组为O(n^2)

代码

//快速排序
public static void quickSort(int[] arr, int left, int right) {
    if (left < right) {
        int pivot = partition(arr, left, right);
        quickSort(arr, left, pivot - 1);
        quickSort(arr, pivot + 1, right);
    }
}

//分区
private static int partition(int[] arr, int left, int right) {
    int pivot = arr[left];
    while (left < right) {
        while (left < right && arr[right] >= pivot) {
            right--;
        }
        arr[left] = arr[right];
        while (left < right && arr[left] <= pivot) {
            left++;
        }
        arr[right] = arr[left];
    }
    arr[left] = pivot;
    return left;
}
//测试算法
public static void main(String[] args) {
    int[] arr = {109, 108, 107, 106, 105, 104, 103, 102, 1011};
    quickSort(arr, 0, arr.length - 1);
    for (int i : arr) {
        System.out.println(i);
    }

}