快速排序

<?php
/*
    算法复杂度:(1)最好的情况和正常情况是:N*logN;
              (2)最坏的情况是正着排好序的数组复杂度是:O(N^2);
    主要思想:
                选取一个元素作为 pivot,随便取哪个位置的都行,一般取第一个;
                将数值小于 pivot 的数字都放到 pivot 的左边,大于的放在右边;
                那么,此时 pivot 这个数的位置就是排好序后的位置了。
                再递归处理该 pivot 之前的数组,和之后的数组就行了。
                -- 第二种方式貌似更好理解写。
*/
function QuickSort( & $arr, $left, $right) {    // 使用数组引用
        /*
            递归的结束条件。同时也是该函数执行的前提。————数组元素个数小于1则推出。
            两个元素:$left = 0; $right = 1. 即:0 ~ 1
        */
        if($right - $left <= 0) {
            return 0;
        }
    /*
        采用“挖坑填数”的方式来对一个数组的内容进行一次调整:
        1、$i = $Left; $j = $Right; 将基准数挖出(存放到$pivot),形成第一个坑$arr[$i] ——一般取数组的第一个值,所以是$arr[$i]
        2、$j--; 先由后向前找比基准数小的数,找到后,挖出此数填在前一个坑$arr[$i]中.
        3、$i++; 再由前向后找比基准数大的数,找到后,挖出此数填在前一个坑$arr[$j]中.
        4、然后,重复执行2、3步,直到$i==$j.
        5、此时,已经结束对一个数组的调整,将$pivot的值填入留下的坑中$arr[$i]
    */    
        $i = $left;
        $j = $right;
        $pivot = $arr[$left];    //$arr[$i] = $arr[$left] 就是第一个坑
        $hole_idx = $left;    //保存当前坑的索引下标

        while ($i < $j) {

            //先从右边向左开始找小于pivot的数
            while ($i<$j && $arr[$j]>=$pivot) {    //如果找到小于$pivot的数,则停止循环!
                $j--;
            }
            if ($i < $j) {
                //将$arr[$j]填入$arr[$hole_idx]会形成一个新的坑
                $arr[$hole_idx] = $arr[$j];
                $hole_idx = $j;
            }

            //从左边向右找大于pivot的数
            while ($i<$j && $arr[$i]<=$pivot) {        //也可以使用 < 号    
                $i++;
            }
            if ($i < $j) {
                $arr[$hole_idx] = $arr[$i];
                $hole_idx = $i;
            }
            $arr[$i] = $pivot;    //退出一次数组操作时,$i==$j,将$pivot填入这个坑中
        }

        //pivot已经放到了合适的位置,不需要再比较。所以是$i-1
        QuickSort($arr, $left, $i-1);    
        QuickSort($arr, $i+1, $right);
}

/*  
    与“挖坑填数”不太一样的另外一种方式:方法类似于冒泡排序的“两两交换”
    1、$i = $left; $j = $right;
    2、设置基准数,一般选取第一个
    3、从右边找到大于基准数的元素    
    4、从左边找到小于....
    5、交换这两个数(两两交换)
    6、重复 3-5 步操作
    7、执行完此操作后,把基准数和$arr[$i](或$arr[$j])交换
    8、递归执行

    因为快速排序的这种两两交换的思路比较相似,所以也有说这是冒泡排序的改进算法。
*/
    function QuickSort2( & $arr, $left, $right) {    // 使用数组引用
        
        if($right - $left <= 0) return 0;

        $i = $left;
        $j = $right;
        $pivot = $arr[$left];

        while ($j > $i) {    
            //先从右边向左开始找小于pivot的数
            while ($j>$i && $arr[$j]>=$pivot) {    // <=
                $j--;
            }
            while ($j>$i && $arr[$i]<=$pivot) {    // >=
                $i++;
            }
            if ($j > $i) {
                $tmp = $arr[$i];
                $arr[$i] = $arr[$j];
                $arr[$j] = $tmp;
            }
        }
        $arr[$left] = $arr[$i];
        $arr[$i] = $pivot;        
        
        QuickSort2($arr, $left, $i-1);
        QuickSort2($arr, $i+1, $right);
    }    

$arr = array(64, 64, 76, 19, 27, 123, 64, 56, 4, 64, 37, 8, 1);

/*
echo "<br/>";
QuickSort2($arr, 0, 10-1);
print_arr_values($arr);
*/

QuickSort($arr, 0, count($arr)-1);    //N个元素的数组:0 ~ N-1
print_arr_values($arr);

function print_arr_values($ar) {
    echo "<br/>";
    foreach ($ar as $key => $value) {
        echo "<strong style=\"font-size:22px;\">", $value, 
             "</strong>", "&nbsp;&nbsp;&nbsp;&nbsp;";
    }
}

参考:https://blog.csdn.net/MoreWindows/article/details/6684558

posted on 2018-10-21 10:21  DoittioD  阅读(144)  评论(0编辑  收藏  举报