快速排序

快速排序


一、简介:

快速排序(Quicksort)是对冒泡排序的一种改进。
它的基本思想是:

  通过一趟排序将要排序的数据分割成独立的两部分,
  其中一部分的所有数据都比另外一部分的所有数据都要小,
  然后再按此方法对这两部分数据分别进行快速排序,
  整个排序过程可以递归进行,
  以此达到整个数据变成有序序列。

算法稳定性: 不稳定排序算法。


二、代码示例:

第一种,笨方法,根据基本思想,递归左右分割数组,但这样太浪费空间:

/**
 * 快速排序
 * @param  array  $arr 数组
 * @param  boolean $asc 是否升序
 * @return array
 */
function quick_sort($arr){
    if(!is_array($arr)){
        return [];
    }
    $len = count($arr);
    if($len <= 1){
        return $arr;
    }else if($len == 2){
        if($arr[0]>$arr[1]){
            return array($arr[1],$arr[0]);
        }else{
            return $arr;
        }
    }
    $left_arr = [];
    $right_arr = [];
    $middle_value = $arr[0];//标尺选择第一个元素
    for ($i=1; $i < $len; $i++) { 
        if($arr[$i]<$middle_value){
            $left_arr[] = $arr[$i];
        }else{
            $right_arr[] = $arr[$i];
        }
    }
    $left = quick_sort($left_arr);
    $right = quick_sort($right_arr);
    return array_merge($left,array($middle_value),$right);
}

第二种,精巧的方式:

(左指针、右指针同时向中间移动,不定义新的数组,就不消耗额外的空间,使用引用传值,注意会改变原有变量)

/**
 * 快速排序
 * @param  [type]  &$arr  数组
 * @param  integer $begin 开始位置
 * @param  [type]  $end   结束位置
 * @return [type]         null
 */
function quick_sort(&$arr,$begin=0,$end=null){
    if(!is_array($arr)){
        return;
    }
    $len = count($arr);
    if($len <= 1){
        return;
    }
    if($end === null){
        $end = $len - 1;
    }
    if($end - $begin <= 1){
        return;
    }
    $value = $arr[$begin];//以第一个为标尺值
    $right_to_left = true;//是否从右到左
    $p1 = $begin;//左侧指针
    $p2 = $end;//右侧指针
    while($p1<$p2){
        if($right_to_left){
            //从右侧开始,每项与标尺值比较,
      //若比标尺值小,则把值放到前边,然后换循环方向,从左侧开始
            for ($i=$p2; $i>$p1; $i--) { 
                if($arr[$i]<=$value){
                    $arr[$p1++] = $arr[$i];
                    $right_to_left = false;
                    $p2 = $i;
                    continue 2;
                }
            }
            $p2 = $p1;
        }else{
            //从左侧开始,每项与标尺值比较,
            //若比标尺值大,则把值放到前边,然后换循环方向,从右侧开始
            for ($i=$p1; $i < $p2; $i++) { 
                if($arr[$i]>=$value){
                    $arr[$p2--] = $arr[$i];
                    $right_to_left = true;
                    $p1 = $i;
                    continue 2;
                }
            }
            $p1 = $p2;
        }
    }
    $arr[$p1] = $value;
    quick_sort($arr,$begin,$p1-1);
    quick_sort($arr,$p1+1,$end);
}


原文地址:https://www.cnblogs.com/gyfluck/p/10571889.html