冒泡排序:
冒牌排序是最经常见的排序算法之一了,因为太简单了,思路正如名字一样,冒泡---把小的往上(前)冒,直到最后有序
function sortArr($arr) { $length = count($arr); for($i=0;$i<$length-1;$i++) { for($k=$length-1;$k>$i;$k--){ if($arr[$k]<$arr[$k-1]){ $arr[$k] = $arr[$k] ^ $arr[$k-1]; $arr[$k-1] = $arr[$k] ^ $arr[$k-1]; $arr[$k] = $arr[$k] ^ $arr[$k-1]; } } } }
以上为冒泡排序主要代码
插入排序:
首先就是待排序数组第一个默认有序,接着看第二个元素与前面有序元素(即第一个),如果第二个元素小于第一个元素,就把第二个元素插入到第一个元素前面,这样前面两个元素就是有序的;接下来第三个元素先和前面排序好的第二个元素比较,如果比第二个小就插入到第二个元素之前,这样再和第一个元素比较(这么说不会饶吧),然后我们这里注意到,第三个元素要和第二个元素比较,比第二个元素小就插入到第二个元素之前,再和第一个元素比较,如果比第一个元素小,就插入到第一个元素里,那我们是不是可以优化减少交换次数呢?也就是我们省去和第二个元素交换;
假设数组如下,前面两个元素23,25已经有序:
23 | 25 | 22 | 12 | 8 | 7 |
默认情况下22先和25比较,因为比25小,所以插入到25之前
23 | 22 | 25 | 12 | 8 | 7 |
这样有一次交换IO吧,接下来22又和23比较,发生22比23小,于是又交换啦!
我们的优化方法是用一个临时变量$tmp存储待比较的那个值,和前面有序数组比较,如果待比较值小于前面的值,就把前面的值复制一份到他下标下一个元素位置,直到遇到比他小的$tmp就和当前元素交换。
function insertSort($arr) { $len = count($arr); //默认第一个元素有序,所以下标从1开始; for($i=1;$i<$len;$i++){ $tmp = $arr[$i]; for($j=$i;$j>0&&$arr[$j-1]>$tmp;$j--) { $arr[$j] = $arr[$j-1]; } $arr[$j]=$tmp; } }
选择排序:
感觉和插入排序很像,首先是把数组第一个元素当做是最小的元素,有序啦,然后遍历整个数组,找出最小的一个元素,和第一个元素交换(第一个元素也小于它),于是真正意义上的最小元素就已经在数组开头第一个下标位置了。
function selectionSort(&$array){ $len=count($array); for($i=0;$i<$len-1;$i++){ $min=$i; for($j=$i+1;$j<$len;$j++){ //表明当前最小的还比当前的元素大 min = $array[$min]>$array[$j]?$j:$min; } if($min!=$i){ $array[$min] = $array[$min] ^ $array[$i]; $array[$i] = $array[$min] ^ $array[$i]; $array[$min] = $array[$min] ^ $array[$i]; } } return $array; }
希尔排序:
function shell_sort($arr){ $len = count($arr); $f = 3;// 定义因子 $h = 1;// 最小为1 while ($h < $len/$f){ $h = $f*$h + 1; // 1, 4, 13, 40, 121, 364, 1093, ... } while ($h >= 1){ for ($i = $h; $i < $len; $i++){ for ($j = $i; $j >= $h; $j -= $h){ if ($arr[$j] < $arr[$j-$h]){ $temp = $arr[$j]; $arr[$j] = $arr[$j-$h]; $arr[$j-$h] = $temp; } } } $h = intval($h/$f); } }
希尔排序是基于插入排序的,正如插入排序,如果我的最小值在最后面,那么他是不是需要N-1次移动,希尔排序改进了这个缺点。希尔排序思想是使数组任意间隔为h的元素都是有序,比如某个时间这个h是3,也就是数组第一个,第四个,第七个……为一组有序,第二个,第五个,第八个为一组有序^-^懂了吧,此文虽然说是O(N^2)级别算法,但是希尔排序是突破了这个限制的,严格来说比O(N^2)快很多。
emmm相信很多人会有疑问$h为什么要这么设置,其实这个问题不好说,算法一书也说至今无法证明哪一个递增序列是最好的,而使用递增序列1,4,13,40,121,364……所需要的比较次数不会超出N的若干倍乘以递增序列长度,并且大量的实验证明平均每个增幅所带来的比较次数约为N1/5