冒泡排序算法【PHP描述】

说起排序算法,最经见也最经常问的莫过于冒泡算法了。因为他够简单粗暴,那么今天我们一起来学习下冒泡算法的PHP描述。

概念:什么是冒泡排序算法?  

1.冒泡排序(Bubble Sort),是一种计算机科学领域的较简单的排序算法。
它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。
走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。
这个算法的名字由来是因为越大的元素会经由交换慢慢“浮”到数列的顶端,故名“冒泡排序”。 -- 《度娘》


我们再来看下示意图(交换第一次时的示意图),图一:


再来一张动态排序图,图二


分析:如何实现冒泡排序算法? 

实现过程就像图一所示一样,就是从第一位数开始不断比较相邻的两个数,如果条件满足就调换顺序,这里可以用for循环轻易实现:

    

for($i=0;$i<count($arr)-1;$i++){
	if($arr[$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循环整合一下,就可以完成简单的冒泡排序了。

<?php
//冒泡排序,PHP描述,默认升序;
function bubble($arr,$type="asc"){
    $length = count($arr);
    //$i表示每次循环所需要比较的次数
    for($i=$length-1;$i>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)。

假如这些元素原本就是有序的呢又或者经过某次的循环已经变成有序了呢?如果是已经有序的那么我们不应该再让它继续循环而浪费性能,应该在某次遍历的时候发现没有已经没有任何可以交互元素的时候结束掉排序。我们可以定义一个交换计数器来控制这个行为:

<?php
//冒泡排序,PHP描述,默认升序;
function bubble($arr,$type="asc"){
    $length = count($arr);
    //$i表示每次循环所需要比较的次数
    for($i=$length-1;$i>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) (遍历所有才完成排序)   

关于冒泡排序先学习到这,如有错误,欢迎指出。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值