分享

冒泡排序的实现和优化

 昵称11350173 2012-12-21

作者:韩忠康 来自:传智播客php论坛http://bbs./thread-7145-1-1.html

冒泡排序:

假设数组的长度为N,数组的索引是由0开始。


依次比较相邻的两个数,如果前面的数大于后边的数则交换2个数。

及在一轮的比较中,依次取得第一个元素到倒数第二个元素,分别与其后相邻的元素进行比较,前面的元素大于后面的元素则交换。这样经过一轮的比较,最大的元素则交换到最后的的位置上。

下面继续按照相同的比较方式比较余下的N-1个元素。直到比较到最后一个元素。


按照冒泡排序的描述,容易写出程序语言,利用双重循环完成。外层循环控制比较的轮数,如果有N个元素,则需要比较N-1轮。内层循环控制每一轮内参与比较的次数,第一轮需要比较N-1次,第二轮需要比较N-2次,以此类推。

看代码:

下面是PHP代码实现:function bubbleSort1(&$arr) {


      $len = count($arr);//取出数组长度


      for($i=0; $i<$len-1; ++$i) {//轮数


            for($j=0; $j<$len-$i-1; ++$j) {//每轮比较次数


                  if($arr[$j] > $arr[$j+1]) {


                        //交换


                        $temp = $arr[$j];


                        $arr[$j] = $arr[$j+1];


                        $arr[$j+1] = $temp;


                  }


                  //print_r($arr); echo ' ';//去掉注释查看


            }


            //echo '


';


      }


    return 1;


}

复制代码这样就按照冒泡的描述,完成了基本编码。

我们现在考虑以下上面的运行过程,

第一轮 需要比较 N-1次,

第二轮 需要比较 N-2次,

第i轮 需要比较    N-i次,

由此可以看出 这个算法的时间复杂度为O(n^2)。


注意:文档中的三个例子都使用的如下的测试数据:$arr = array(4, 7, 6, 3, 9, 5, 8);可以去掉程序中的注释查看比较结果。



在比较的过程中,其实是有些比较过程是可以省略。当在一轮的比较过程中如果没有发生交换,没有交换说明没有前面的元素大于后面元素的情况,意味着排序完成。

下面重写编写代码实现:function bubbleSort2(&$arr) {


      $len = count($arr);//取出数组长度


      $flag = true;//设置标志,默认为true,表示需要继续比较


      for($i=0; $flag && $i<$len-1; ++$i) {//轮数,标志为真,继续比较


            $flag=false;//将标志设为false,表示还没有发生交换


            for($j=0; $j<$len-$i-1; ++$j) {//每轮比较次数


                  if($arr[$j] > $arr[$j+1]) {//交换


                        $temp = $arr[$j];


                        $arr[$j] = $arr[$j+1];


                        $arr[$j+1] = $temp;


                        $flag = true;//交换,设置为true表示需要继续比较


                  }


                  //print_r($arr);echo '


';//可以将注释去掉 查看比较结果


            }


            //echo '


';


  }


      return 1;


}

复制代码上面的排序,会在某轮没有交换时,就比较完毕了:

例如:在上面的循环的第四轮,比较如下:

Array(    [0] => 3    [1] => 4    [2] => 5    [3] => 6    [4] => 7    [5] => 8    [6] => 9) //第四轮后的比较的结果

Array(    [0] => 3    [1] => 4    [2] => 5    [3] => 6    [4] => 7    [5] => 8    [6] => 9)

Array(    [0] => 3    [1] => 4    [2] => 5    [3] => 6    [4] => 7    [5] => 8    [6] => 9)

Array(    [0] => 3    [1] => 4    [2] => 5    [3] => 6    [4] => 7    [5] => 8    [6] => 9)

//比较后 没有发生交换,则第五轮不需要再继续的,因此排序完成!优化过后,省去了2轮比较。


下面可以再看,我们上面记录的是否发生了交换,按照同样的思路,我们可以记录交换发生的最后位置。例如如果有5个元素没有排好顺序的话,但是在这五个元素比较时,如果第2个和第3个发生了交换,而后面2个的没有发生交换,说明后面的已经排好顺序了,那么在下次比较的时候就不需要在比较后面的3个元素了,直接比较到第2个元素即可。

这样还会省略掉几次比较次数:

再看编码实现:function bubbleSort3(&$arr) {


      $len = count($arr);//取出数组长度


      $flag = $len-1;//设置标志,默认为长度-2,表示需要比较到的位置


      while($flag > 0) {


            $pos = $flag;//设置需要比较到的位置,为上次的标志位


            $flag = 0;//设置为0 表示没有发生交换,那么就说明不用再比较了


            for($j=0; $j<$pos; ++$j) {//每轮比较次数,比较到最后交换的元素即可


                  if($arr[$j] > $arr[$j+1]) {//交换


       $temp = $arr[$j];


                      $arr[$j] = $arr[$j+1];


                      $arr[$j+1] = $temp;


                      $flag = $j;//交换,设置为true表示需要继续比较


                }


                //print_r($arr);echo $flag, '


';//打开注释,查看比较结果


            }


     //echo '


';


      }


      return 1;


}

复制代码经过上面的更改,可能再次省掉部分比较:

例如:

在第二轮比较后,发现最后交换的下标为3, 则下轮比较到下标为3的元素就可以了。

大家可以去掉注释查看比较的过程。


对了,由于在排序的过程中,总是大数放在小数后边,就像气泡上升,因此成为冒泡排序。


还有,即使使用了优化后的排序算法,也没有从根本上解决效率低的问题,还是效率不高的排序算法。希望大家再学习其他的排序算法完成更好的更快的排序。


就到这,引玉之砖。大家讨论。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多