代码改变世界

php 冒泡排序的两种思路以及优化

2017-11-29 15:29  折翼的鸟  阅读(1664)  评论(0编辑  收藏  举报

php冒泡排序,两种思路,时间复杂度都是O(n^2),当然最优的时间复杂度就是O(n),以下说的都是正序排列(倒序的话,把内层循环的大于号换成小于号就好了)

 

第一种冒泡排序

思路就是把第一个数跟所有的数比较,如果碰到比第一个数还小的数字,就把他俩位置交换下,然后把交换后的数字继续往后比较...
这样第一轮交换能得出什么呢,就是第一轮交换完,数组的第一个位置,一定是最小的数
循环体内,每次$j = $i + 1, 因为外层每循环一次已经把最小的数压到数字头部了, 没必要从头开始比较了

$numbers = array(-2, 5, 3, 1, -3, -4);
for ($i=0;$i<count($numbers);$i++) {
    for ($j=$i+1;$j<count($numbers);$j++) {
        if ($numbers[$i] > $numbers[$j]) {
            $tmp         = $numbers[$i];
            $numbers[$i] = $numbers[$j];
            $numbers[$j] = $tmp;
        }
    }
    // var_dump($numbers);
}
var_dump($numbers);exit;


第一轮交换的过程:拿数组的第一位-2跟5比,发现没有我小,跳过,拿-2跟3比,发小没有我小跳过...
拿-2跟-3比的时候,发小比我还小,两个交换下位置,下次循环的时候数组第一位已经发生了变化,是-3。嗯,仔细想想
然后循环还没完,继续拿数组的第一位(-3),跟数组最后一位-4比较,又交换下位置...
结果:[-4, 5, 3, 1, -2, -3]
第二轮循环时候拿5跟数组后面的开始比较,没必要跟前面的比了,因为经过上一轮的比较,第一位肯定是最小的...

 

 

第二种冒泡排序

思路就是一组一组数字(相邻的两个数)比较,如果大于后面的数字就发生交换,这样比较完的结果就是会把最大的数移动到最后的位置

$numbers = array(-2, 5, 3, 1, -3, -4);
for ($i = 0; $i < count($numbers); $i++) {
    for ($j = 0; $j < count($numbers) - $i - 1; $j++) {
        if ($numbers[$j] > $numbers[$j + 1]) {
            $temp = $numbers[$j];
            $numbers[$j] = $numbers[$j + 1];
            $numbers[$j + 1] = $temp;
        }
    }
    var_dump($numbers);
}

第一轮交换完过程就是: -2不大于5不交换,5大于3交换,5大于1交换,5大于-3交换,5大约-4交换....
结果: [-2, 3, 1, -3, -4,5]
...
第二轮交换的时候,注意条件$j < count($numbers) - $i - 1; 已经不跟最后一个比较了,因为你懂的...

 

关于优化
如果数组是: [5,1,2,3,4] 套用我们第二种思路的话, 是不是我们第一轮循环完(结果是[1,2,3,4,5]), 就可以终止循环了.

加个变量,如果里面没有发生交换,就意味着数组目前就是有序的,可以退出循环了

$numbers = [5,1,2,3,4];
for ($i = 0; $i < count($numbers); $i++) {
    $flag = 1;
    for ($j = 0; $j < count($numbers) - $i - 1; $j++) {
        if ($numbers[$j] > $numbers[$j + 1]) {
            $flag = 0;
            $temp = $numbers[$j];
            $numbers[$j] = $numbers[$j + 1];
            $numbers[$j + 1] = $temp;
        }
    }
    if($flag) break;
}
var_dump($numbers);exit;