一 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) 。 這時還用冒泡算法。 明天再來看結果。