说起排序算法,最经见也最经常问的莫过于冒泡算法了。因为他够简单粗暴,那么今天我们一起来学习下冒泡算法的PHP描述。
概念:什么是冒泡排序算法?
我们再来看下示意图(交换第一次时的示意图),图一:
再来一张动态排序图,图二
分析:如何实现冒泡排序算法?
实现过程就像图一所示一样,就是从第一位数开始不断比较相邻的两个数,如果条件满足就调换顺序,这里可以用for循环轻易实现:
for($i=0;$i $arr[$i+1]){
//条件满足,交换位置
$temp = $arr[$i];
$arr[$i] = $arr[$i+1];
$arr[$i+1] = $temp;
}
}
但是这样子的一个for循环一次只能冒泡出一个 最大值(最小值),所以我们需要再加一个for循环,控制冒出一个最大值(最小值)之后继续冒第二大(小)值,如此类推就能够把所有的数字冒泡排序了:
//$i表示每次循环所需要比较的次数
for($i=count($arr)-1;$i>0;$i--){
//其他代码
}
综上,我们把两个for循环整合一下,就可以完成简单的冒泡排序了。
0;$i--){
for($j=0;$j<$i;$j++){
if($arr[$j] > $arr[$j+1]){
//如果符合条件就交换相邻两个数的位置;
$temp = $arr[$j];
$arr[$j] = $arr[$j+1];
$arr[$j+1] = $temp;
}
}
}
//如果要降序的话,只需要把整个数组颠倒就可以了;
$new_arr = array();
if($type == "desc"){
for($i=$length-1;$i>=0;$i--){
$new_arr[] = $arr[$i];
}
}
return $type == "desc" ? $new_arr : $arr;
}
$arr = array(54,26,93,17,77,31,44,55,20);
var_dump(bubble($arr));
var_dump(bubble($arr,"desc"));
?>
以上输出如下:
优化
到此,冒泡排序的算法算是做好了,我们来看下他的时间复杂度:
因为无论在何种情况,他都需要经过两层遍历元素,所以我们可以认为时间复杂度无论在何种情况下都为:O(n^2)。
假如这些元素原本就是有序的呢又或者经过某次的循环已经变成有序了呢?如果是已经有序的那么我们不应该再让它继续循环而浪费性能,应该在某次遍历的时候发现没有已经没有任何可以交互元素的时候结束掉排序。我们可以定义一个交换计数器来控制这个行为:
0;$i--){
$count = 0; //定义交换计数器,如果在某次比较循环当中没有交换过位置,可以认为已完成排序;
for($j=0;$j<$i;$j++){
if($arr[$j] > $arr[$j+1]){
//如果符合条件就交换相邻两个数的位置;
$temp = $arr[$j];
$arr[$j] = $arr[$j+1];
$arr[$j+1] = $temp;
$count++;
}
}
if(!$count){
break; //如果在某次循环中并没有交换元素位置,则认为已经完成排序,退出循环。
}
}
//如果要降序的话,只需要把整个数组颠倒就可以了;
$new_arr = array();
if($type == "desc"){
for($i=$length-1;$i>=0;$i--){
$new_arr[] = $arr[$i];
}
}
return $type == "desc" ? $new_arr : $arr;
}
$arr = array(54,26,93,17,77,31,44,55,20);
var_dump(bubble($arr));
var_dump(bubble($arr,"desc"));
?>
(以上输出结果与未加入计数器时的结果一致,这里不再上图。)
我们再来看下优化后的算法的时间复杂度:
最优时间复杂度:O(n) (表示遍历一次之后发现没有任何可以交换的元素的,结束排序)
最坏时间复杂度:O(n^2) (遍历所有才完成排序)
关于冒泡排序先学习到这,如有错误,欢迎指出。