前言
關於對數組的排序,在演算法中有很多方法,較為簡單的有冒泡,選擇,插入等一些使人熟知的算術方法,在當今這個追求效率的社會,演算法的好壞對程式本身有著重要的影響。而我們在判定演算法好壞的時候,時間複雜度是一個重要的尺規,
而對數組排序中,插入排序和快速排序的效率要比冒泡和選擇排序的效率要高,而今天就來聊一聊插入排序和快速排序的原理和實現。
插入排序
插入排序的基本操作就是將一個資料插入到已經排好序的有序資料中,從而得到一個新的有序資料,把排序的數組分成兩部分:第一部分包含了這個數組的所有元素,但將最後一個元素除外(讓數組多一個空間才有插入的位置),而第二部分就只包含這一個元素(即待插入元素)。在第一部分排序完成後,再將這個最後元素插入到已排好序的第一部分中。
原理示意圖
通俗易懂的說就是:
我們在對數組進行排序是,可以將數組的第一個數字看成是一個有序的數組,而後面的數字是一個無序的數組。遍曆後面的無序數組和前面有序的數組進行比較,當發現需要插入時,有序數組向後挪移一位,插入資料。
案列(從小到大排序):
有一個數組:
$arr = array(1,2,10,5,3);
假設第一個數1是有序數組。即:
有序(1)無序(2 , 10 , 5 , 3);
遍曆無序數組
for($i = 1; $i < $total; $i++){$insert = $arr[$i];//先記錄帶插入的資料;$j = $i - 1;
利用while迴圈進行判斷插入的位置
while($j >= 0 && $arr[$j] > $insert){
判斷條件$j必須大於等於0,當前面已排完序的數比待排序的數大,這是就需要先前的數向後挪一位即:
$arr[$j + 1] = $arr[$j];$j--;
在這裡不要擔心$arr[$i]被覆蓋了,我們已經在for迴圈之後記錄的待排序的數值。
當不滿足while的迴圈判斷條件的時候跳出迴圈,並賦值
$arr[$j + 1] = $insert;
在這裡可以進行判斷當沒有進入迴圈的時候,$j + 1 = $i 這時不用進行賦值。
代碼:
<?php $arr = array(1,2,10,5,3);function insertSort(&$arr){$total = count($arr);for($i = 1; $i < $total; $i++){$insert = $arr[$i];//先記錄帶插入的資料;$j = $i - 1;while($j >= 0 && $arr[$j] > $insert){$arr[$j + 1] = $arr[$j];$j--;}if($j +1 != $i){$arr[$j + 1] = $insert;}}} insertSort($arr); echo '<pre>'; var_dump($arr);
數字流程示意圖:
插入排序的時間複雜度為O(n^2)。是穩定的排序方法。
快速排序
通過一趟排序將要排序的資料分割成獨立的兩部分,其中一部分的所有資料都比另外一部分的所有資料都要小,然後再按此方法對這兩部分資料分別進行快速排序,整個排序過程可以遞迴進行,以此達到整個資料變成有序序列。
快速排序的樣本:
有一個數組:
$arr = array(6,2,7,3,8,9);
我們選取第一個數字為界:
$k=$arr[0];//記錄k的值 把數組分成兩個部分,比k小的在左邊,比k大的在右邊。
定義兩個數組一個儲存比k小的數的值,一個儲存比k大的值。
然後遍曆數組,和$k的值進行比較,遍曆完成後,使用遞迴,不斷的分解數組,直到不能再分解為止。
$x=quickSort($x);$y=quickSort($y);return array_merge($x,array($k),$y);//數組合并。
代碼(易於理解的一種寫法):
<?php $arr = array(6,2,7,3,8,9); function quickSort(&$arr){ if(count($arr)>1){ $k=$arr[0];//記錄k的值 把數組分成兩個部分,比k小的在左邊,比k大的在右邊。 $x=array(); $y=array(); $_size=count($arr); for($i=1;$i<$_size;$i++){ if($arr[$i]<=$k){ $x[]=$arr[$i]; }else if($arr[$i]>$k){ $y[]=$arr[$i]; } } $x=quickSort($x); $y=quickSort($y); return array_merge($x,array($k),$y);//數組合并。 }else{ return $arr; } } echo '<pre>'; var_dump(quickSort($arr));
(注意:這種方法雖然符合快速排序的思想,但是會在遞迴過程中建立大量的數組存放資料,當資料量大的時候會造成 Allowed memory size of 134217728 bytes exhausted也就是記憶體耗盡) 總結 插入排序和快速排序的差別:插入排序的效率比快速排序的效率要低。我們可以用一個存放20萬個資料數組,使用兩種方法進行比較。
<span style="font-size:18px;"> $arr = array();for($i = 0; $i < 200000; $i++){$arr[] = rand(1, 3000);}</span>
通過執行前後時間的對比
插入排序:
快速排序:
可以看出插入排序的執行時間超過了php的預設時間。而快速排序用了7秒