04-快速排序

1 基本思想

通过一趟排序将待排记录分隔成独立的两部分,其中一部分记录的关键字均比另一部分的关键字小,则可分别对这两部分记录继续进行排序,以达到整个序列有序。

2 算法过程

1、从数列中挑出一个元素,称为 “基准”(pivot); 2、将待排序元素进行分区,比基准值小的元素放在基准值前面,比基准值大的元素放在基准值后面。分区结束后,该基准值就处于数组的中间位置;这个称为分区(partition)操作; 3、递归地(recursive)对左右两个分区重复以上步骤直到所有元素都是有序的。

3 算法图解

算法图解

4 PHP代码实现

/**
 * 快速排序: 每次选最左边的点, 将数组划分为左右两部分, 保证右边的比选点大,左边的都比选点小, 对左右两边递归
 * 时间复杂度: 最好 O(nlogn) 最差 O(n2)
 * 空间复杂度: O(1)
 * 不稳定排序
 */
function quickSort(&$arr, $start, $end) {
    $i = $start;
    $j = $end;
    $pivot = $arr[$start];
    while ($j > $i) {
        // 右边有比选点小的, 扔到左边, 让下一while得以继续
        while ($arr[$j] >= $pivot && $j > $i) {
            $j--;
        }
        if ($arr[$j] <= $pivot) {
            $temp = $arr[$j];
            $arr[$j] = $arr[$i];
            $arr[$i] = $temp;
        }
        // 左边的有比选点大的就,扔到右边, 让上一while得以继续
        while ($arr[$i] <= $pivot && $j > $i) {
            $i++;
        }
        if ($arr[$i] >= $pivot) {
            $temp = $arr[$i];
            $arr[$i] = $arr[$j];
            $arr[$j] = $temp;
        }
    }
    // 循环结束后,i,j都指向选点
    if ($i > $start) {
        quickSort($arr, $start, $i - 1);
    }
    if ($j < $end) {
        quickSort($arr, $j + 1, $end);
    }
}

$arr = [38, 19, 29, 91, 85, 12, 41, 21];
quickSort($arr, 0, count($arr) - 1);
print_r($arr);

5 效率分析

1、时间复杂度:O(nlogn) 最好的情况:当分区选取的基准元素为待排序元素中的"中值",时间复杂度为O(nlogn); 最坏的情况:当分区选取的基准元素为待排序元素中的最大或最小值,时间复杂度为O(n²)。 2、空间复杂度:O(log2n),是不稳定排序。


Last modified March 8, 2022: Fix image path (67fc7f5)