没吃过猪肉,总得见过猪跑。快速排序之所以这么被众所周知,除了性能略屌之外,还因为面试必备所以为大家所知。

    14. 排序篇之快速排序之入门篇 - 图1

    标题叫做入门篇,因为快排其实内含的原理和思想很深邃也很多,分治和递归都是有所体现的。快排的主题中心思想就是首先选中一个基准数(不作死的话,我建议你选中间那个),然后将剩余的挨个和基准数比大小,凡是比基准数大的放到一侧,凡是比基准数小的放到另一侧,然后再对这两侧的数据集重复上面的操作。一波儿操作猛如虎后,数据就能被按照一定顺序排好了。

    所以,一般说来,可以尝试通过递归来解决一下核心问题,你们感受一下:

    1. <?php
    2. $arr = [ 345,23,567,345345,234,122322,5464657,23423 ];
    3. function quick( array $arr ){
    4. $length = count( $arr );
    5. if( 1 == $length ){
    6. return $arr;
    7. }
    8. // 位运算,不明白的同学自己补充下 >> 的含义
    9. $mid_index = $length >> 1;
    10. $left = [];
    11. $right = [];
    12. for( $i = 0; $i < $length; $i++ ){
    13. if( $i == $mid_index ){
    14. continue;
    15. }
    16. // 如果比基准数大
    17. if( $arr[ $i ] > $arr[ $mid_index ] ){
    18. $right[] = $arr[ $i ];
    19. }
    20. // 如果比基准数小
    21. else if( $arr[ $i ] < $arr[ $mid_index ] ){
    22. $left[] = $arr[ $i ];
    23. }
    24. }
    25. return array_merge( $left, array( $arr[ $mid_index ] ), $right );
    26. }
    27. print_r( quick( $arr ) );

    运行一下,你们看到结果如下:

    14. 排序篇之快速排序之入门篇 - 图2

    嗯,是的,上述代码有问题,我故意这么干的。实际上,有为青年大概能看出来这是将数组以234为基准数进行了一轮排列,所以比234小的都已经到前排变成了left数组,比234大的都到后排变成了right数组。但是,left和right数组本身却依旧是乱序的,那么下一步要做的就是对left和right也进行相同的操作即可!

    所以,修改上述代码:

    1. <?php
    2. $arr = [ 345,23,567,345345,234,122322,5464657,23423 ];
    3. function quick( array $arr ){
    4. $length = count( $arr );
    5. if( $length <= 1 ){
    6. return $arr;
    7. }
    8. // 位运算,不明白的同学自己补充下 >> 的含义
    9. $mid_index = $length >> 1;
    10. $left = [];
    11. $right = [];
    12. for( $i = 0; $i < $length; $i++ ){
    13. if( $i == $mid_index ){
    14. continue;
    15. }
    16. // 如果比基准数大
    17. if( $arr[ $i ] > $arr[ $mid_index ] ){
    18. $right[] = $arr[ $i ];
    19. }
    20. // 如果比基准数小
    21. else if( $arr[ $i ] < $arr[ $mid_index ] ){
    22. $left[] = $arr[ $i ];
    23. }
    24. }
    25. return array_merge( quick( $left ), array( $arr[ $mid_index ] ), quick( $right ) );
    26. }
    27. print_r( quick( $arr ) );

    其中,上述代码的第72行,请仔细品悟。比如我问个问题,是quick( $left )先执行?还是quick( $right )先执行?又或者,他们是一边递归一边merge还是等所有排完了再最后merge?