再來一個非常高級的排序算法,快速排序...這個算法是很高效的。
快速排序的思路是,找到一個分割點(中樞點 默認是列表第一個值),把原列表分隔成兩部分,在分割點左側的是都比它小的,在它右側的是都比它大的。然后分別把這兩部分再遞歸調用排序,自然就全部排序完成。
當然最重要的步驟就是切分,然后進行遞歸調用,重復以上分割操作,直到break。代碼示例如下:
第一種實現更能直觀細節展示出快排中的含義:
$arr = array(19, 17, 13, 16,12 , 11, 4, 9, 77, 18); qsort(0, count($arr) - 1, $arr); echo "<pre>"; print_r($arr); /** * @param $low * @param $high * @param $arr * 快速排序 遞歸調用 * 關鍵點在於part動作 */ function qsort($low, $high, &$arr){ if($low < $high){ $pivot = part($low, $high, $arr); qsort($low, $pivot-1, $arr); qsort($pivot+1, $high, $arr); } } /** * @param $low * @param $high * @param $arr * @return mixed * part的核心動作在於-- 中樞點的位置不斷變換,比它小的換到它的左邊,比它大的換到它的右邊 */ function part($low, $high, &$arr){ $pivot = $arr[$low];// 中樞點默認是列表第一個 while($low < $high){ while($low < $high && $arr[$high] >= $pivot){// 右邊選比中樞點小的 $high--; } swap($arr, $low, $high);// 此時中樞點在低位置,而此時的高位置小於中樞點。兩點交換 while($low < $high && $arr[$low] <= $pivot){// 左邊選比中樞點大的 $low++; } swap($arr, $low, $high);// 此時中樞點在高位置,而此時的低位置大於中樞點。兩點交換 } return $low;// 低位此時是中樞點,返回中樞點位置 } /** * @param $arr * @param $i * @param $j * 交換位置 */ function swap(&$arr, $i, $j){ $temp = $arr[$i]; $arr[$i] = $arr[$j]; $arr[$j] = $temp; }
理解快速排序怎么交換值這點尤為關鍵,這個算法很機智。。加深理解算法中的智慧吧~
另一種流傳比較廣的php寫快速排序,切分后的兩邊用兩個數組裝起來。
代碼:
$arr = array(19, 17, 13, 16, 12, 11, 4, 9, 77, 18); echo "<pre>"; print_r(quick_sort($arr)); /** * @param $arr * @return array * 快速排序 */ function quick_sort($arr) { // 遞歸結束: 數組長度為1,直接返回 $length = count($arr); if ($length <= 1) { return $arr; } // 數組元素有多個,則定義兩個空數組 $left = $right = array(); // 使用for循環進行遍歷,默認第一個元素作為中樞點 for ($i = 1; $i < $length; $i++) { // 判斷當前元素的大小 if ($arr[$i] < $arr[0]) { $left[] = $arr[$i]; } else { $right[] = $arr[$i]; } } // 遞歸調用 $left = quick_sort($left); $right = quick_sort($right); // 將所有的結果合並 return array_merge($left, array($arr[0]), $right);// 中間切點 }