php 常用四種排序 冒泡,選擇,插入,快排
---恢復內容開始---
1冒泡排序。 【為描述方便,例子全面為升序排列】
簡述:假設數組有10個數字,從左向右。依次比較,如果前者大於後者,則兩兩交換。每一輪將冒泡一個最大數出來,依次循環,完成排序
流程描述:
-- 第一次 a[0] 與 a[1] 比如果 a[0] > a[1] 則 a[0] 與 a[1] 交換,然後 a[1] 與 a[2] 交換,依次到 a[8] 與 a[9] 交換。 此輪過後 a[9] 必為 a[0-9] 中的最大值。
第二次(此時 a[9]以是最大值) a[0] 與 a[1] 比如果 a[0] > a[1] 則 a[0] 與 a[1] 交換,然後 a[1] 與 a[2] 交換,依次到 a[7] 與 a[8] 交換。 此輪過後 a[8] 必為 a[0-8] 中的最大值。
第三次(此時 a[9]以是最大值,a[8]次大) a[0] 與 a[1] 比如果 a[0] > a[1] 則 a[0] 與 a[1] 交換,然後 a[1] 與 a[2] 交換,依次到 a[6] 與 a[7] 交換。 此輪過後 a[7] 必為 a[0-7] 中的最大值。
-------------- 如此反復,一次冒泡一個最大值出來。
//冒泡排序代碼示例
public function bubbleSort($arr){ //冒泡排序
$len = sizeof($arr); for( $i = 0; $i< $len - 1; $i++){ //冒第幾個泡 for( $j = 0; $j < $len - $i - 1 ; $j++){ //未冒完泡的依次比較,找出最大值 if( $arr[$j] > $arr[$j+1]){ $arr = swap($arr , $j, $j+1); } } } return $arr; } //將數組的第 i j 位互換。 //後面代碼略 public function swap($arr , $i , $j){ // $temp = $arr[$i]; $arr[$i] = $arr[$j]; $arr[$j] = $temp; return $arr; }
2選擇排序
簡述,假設數組有10個數字,從左向右 1 到9 每個與右邊的所有數進行比較,找出右側最小的,並與之替換。
流程描述
-- 第一次 a[0] 逐個與 a[1] - a[9] 比對,找到最小值,然後 a[0]與a[0-9]中的最小值進行替換。替換後 a[0] 為數組最小值 (如果0 正好是最小,則不替換 )
第二次 此時a[0],以是最小值,進行下一步。a[1] 逐個與 a[2] - a[9] 比對,找到最小值,然後 a[1]與a[1-9]最小的進行替換。
第三次 此時a[0],以是最小值,a[1] 為數組次小值(前兩個元素已排好序) a[2] 逐個與 a[3] - a[9] 比對,找到最小值,然後 a[2]與那個a[2-9]最小值的進行替換。
............... 依次循環,完成排序。
//選擇排序代碼示例
function selectSort($arr){ // $len = sizeof($arr); for( $i = 0; $i< $len - 1; $i++){ //從左向右遍歷,每次找出 i 位的最小值.
$minIndex = $i; for( $j = $i+1; $j < $len ; $j++){ //遍歷 i 右邊的不斷的找出最小值。 if( $arr[$minIndex] > $arr[$j]){ $minIndex = $j; } } //位置交換 if( $i != $minIndex){ //把當次最左邊的與向右查找的最小值進行替換。 $arr = $this->swap( $arr , $i , $minIndex);; } } return $arr; }
3 快速排序 (重點)
簡述:設置一個基數,然後對數組進行左右切割。(左邊比基數小,右邊大於等於基數) ,然後再對左邊數組做上述操作。 最後將左 數組 基數 右數據 進行歸並
//快速排序算法 public function quickSort($arr){ $len = sizeof($arr); if( $len <=1 ) return $arr; $base = $arr[0]; //基數 $l_arr = array(); //左邊數組 $r_arr = array(); //右邊數組 for($i = 1;$i<$len ; $i++){ if( $arr[$i] < $base){ $l_arr[]= $arr[$i]; }else{ $r_arr[]=$arr[$i]; } } $l_arr = quickSort($l_arr); $r_arr = quickSort($r_arr); return array_merge($l_arr , array($base) , $r_arr); }
4 插入排序 (附帶介紹,可以略過)
簡述,假設數組有10個數字,從數組第二個開始, 每次向左比較【左邊已是一個有序數組】依次向左找到自己的位置,一個一個比。
受制於語言能力,寫得很饒口。
-- 第一次 a[1] 與 a[0] 比,如果a[1] < a[0] 則 將a[0] 數據移至 a[1] 位 將 a[1] 的值插入到 a[0]位置上。
-- 第二次 a[2] (待插入值) 與 a[0] , a[1] (已經有序) 如果a[2](待插入值) > a[1] 則 a[2] (待插入值) 不動。 如果小於a[1] 則 將原 a[1] 數值移到 a[2] 中,a[2](待插入值) 的值放入到 a[1]中。 再與 a[0] 比,如果大於 a[0] 則 a[0]值放入到 a[1] 中。
public function insertSort($arr){ $len = sizeof($arr); for( $i = 1; $i< $len ; $i++){ $temp = $arr[$i]; for( $j = $i-1; $j>=0; $j--){ //針對一個有序數據,依次找插入位 if($temp < $arr[$j]){ //逐個插入。 $arr[$j+1] = $arr[$j]; $arr[$j] = $temp; }else{ break; } } } return $arr; }
寫在最後:要對大量數據,有量級的概念。 快排的復雜度是 O( N log N) ,冒泡排序是 O(N平方)
僅以1萬個數為例。 快排復雜度是 10000 * Log2 10000 約為 13* 萬 ,冒泡則是 1億。 相差約800倍性能。
如果是10萬個 快排則是 10萬 * log2 100000 約為 170萬 而冒泡則是100億。 瞬間差出約7000 位。
而10萬條數據,在真實場景下,真的不多。
如果說感受不明顯,就跑跑代碼體驗下。
/**性能調試。*/ function bench_profile($starttime , $flag = ‘‘){ $endtime = explode(‘ ‘,microtime()); $thistime = $endtime[0]+$endtime[1]-($starttime[0]+$starttime[1]); $thistime = round($thistime,3); return $flag."-bench:".$thistime." sec"; } $start_time = explode(‘ ‘,microtime()); echo bench_profile($start_time)."<br/>"; $arr = []; for($i=0;$i<10000;$i++){ $arr[]= rand(1,100000); } $arr_insert = quickSort($arr); echo bench_profile($start_time); //1w條跑完時間 -bench:0.053 sec 冒泡算法。 約 45 秒 //10w條跑完時間 -bench:0.77 sec 冒泡算法 約 一個半小時。 //100萬條,跑完時間 16秒。 這時需要放開內存限制 ini_set("memory_limit",-1) 。 這時還用冒泡算法。 明天再來看結果。
php 常用四種排序 冒泡,選擇,插入,快排