最近看了一下冒泡排序这个经典的算法,在网上也看到了很多改进冒泡排序算法的方式,这里总结一下:

冒泡排序最简单的实现方式如下(我用PHP来实现,用其他语言也是一样的):

for($i=0;$i<$arr_count;$i++){for($j=0;$j<$arr_count-1;$j++){if($rand_arr[$j] > $rand_arr[$j+1]){//进行交换$temp = $rand_arr[$j];$rand_arr[$j] = $rand_arr[$j+1];$rand_arr[$j+1] = $temp;}}
}

例如:[ 3 , 1 , 4 , 5 , 6 , 7 , 8 , 9 , 10 , 11 ]—-针对这个数组我们按照基本冒泡排序算法,需要循环count([ 3 , 1 , 4 , 5 , 6 , 7 , 8 , 9 , 10 , 11 ])轮,也就是10轮。

第一轮的排序结果如下:[1,3,4,5,6,7,8,9,10,11]

第二轮的排序结果如下:[1,3,4,5,6,7,8,9,10,11]

第三轮的排序结果如下:[1,3,4,5,6,7,8,9,10,11]

第….轮的排序结果如下:[1,3,4,5,6,7,8,9,10,11]

第十轮的排序结果如下:[1,3,4,5,6,7,8,9,10,11]

通过上面的介绍,会发现,上面的数组其实在第一轮排序后就已经将数组排序好了。后面的几轮排序其实都是无用功。也就是说下面的代码白白走了9遍,一点作用都没发生。

上面的白白执行9遍的代码中,每一遍都能在(n-1)的数据比较,如果数组的长度n极大,这个消耗还是很严重的。所以我们首先要解决一下这个问题,怎么才能不造成无谓的数据比较的资源浪费。

优化策略:在程序中添加标识,用于记录每次外循环过程中,是否发生了数据的交换。如果没有发生数据的交换,就意味者在上一轮的外循环过程中,数据已经排序完成,不需要继续循环比较数据了,我们直接break掉就可以了。如果还存在这数据的交换,就意味着在之前的外部循环中,数据还没有排序好,这一轮排序操作或者接下来的排序操作才可以完成排序工作,我们还需要进行下一轮的排序来完成排序。

$arr_count = count($rand_arr);
for($i=0;$i<$arr_count;$i++){//设置flag变量,用来记录数据是否交换完成$flag = true;for($j=0;$j<$arr_count-1;$j++){if($rand_arr[$j] > $rand_arr[$j+1]){//进行交换$temp = $rand_arr[$j];$rand_arr[$j] = $rand_arr[$j+1];$rand_arr[$j+1] = $temp;$flag = false;}}if($flag){break;}
}

其实,在进行数据排序的过程中,随着排序的进行,数据逐渐从无序变为有序,出现上面情况的可能性会逐步的增高的。

好了,说完上面的问题,咱们再来看下面的问题。当冒泡排序的外部循环每执行一次,就会将最大值(最小值)交换到数组的最前端或者数组的最后端,直接看下面的例子。

经过第一轮排序以后会得到以下的结果:[ 4 , 6 , 2 , 7 , 8 , 0, 9 ] —-也就是说,我们再第一轮求出的最大值9,并且将这个值交换到数组的左部第一的位置上

经过第二轮排序以后会得到以下的结果:[ 4 , 6 , 2 , 7 , 0 , 8 , 9 ] —-也就是说,我们再第二轮求出的次最大值8,并且将这个值交换到数组的左部第二的位置上

……..

依此类推,我们可以发现,每一轮循环完毕,都能求出某个位置上的应有的数据,并且完成交换。那么也就是说数组的左部(右部)逐渐变得有序,且有序部分的长度等于外部循环进行的轮数。既然数组的左部(右部)逐渐变得有序,那么每次循环过程中,我们就不需要再比较数组的左部(右部)的有序的部分了。

优化策略:新增一个变量来记录某次外部循环过程中最后发生的数据交换的位置。使用上面记录的位置来作为下一次外部循环中的内部循环的终止条件,这样就能减少不必要数据比较过程。代码如下:

$arr_count = count($rand_arr);
$last_pos = $arr_count; //记录每一次外部循环过程中,最后进行数据交换的位置
$next_pos = $arr_count; //记录每一次数据交换的位置
for($i=0;$i<$arr_count;$i++){for($j=0;$j<$last_pos-1;$j++){if($rand_arr[$j] > $rand_arr[$j+1]){//进行交换$temp = $rand_arr[$j];$rand_arr[$j] = $rand_arr[$j+1];$rand_arr[$j+1] = $temp;$next_pos = $j+1;}}//如果该轮循环得到的最后的数据交换位置等于上一轮循环得到的数据交换的位置,就意味着数组全部有序了if($last_pos == $next_pos){break;}else{//如果没有全部有序,就将last_pos设置为next_pos$last_pos = $next_pos;}
}

解决了上面的问题,我们还能不能进一步的提高冒泡算法的排序速度嘛?答案是可以的。我们可以采用双向排序的方式,进一步加快排序的速度。看下面的实现的例子:

数组: [ 4 , 3 , 6 , 5 , 9 , 0 , 1 , 7 ]

双向排序之正向排序(从左到右排序):[ 3 , 4 , 5 , 6 , 0 , 1 , 7 , 9] —计算出数组的最大值9,并将元素移动到数组的最右边

双向排序之逆向排序(从右到左排序):[ 0 , 3 , 4 , 5 , 6 , 1 , 7 , 9] —计算出数组的最小值0,并将元素移动到数组的最左边

第一次循环过程,计算出最大值并将该值移动到数组最右边,计算出最小值并将该值移动到数组的最左边。第二次循环过程中,计算出第二大的值并将数据移动到数组右边第二个的位置,计算出第二小的值并将数据移动到数组左边第二个的位置。也会说在一次双向排序循环过程中,求出数组左边以及数组右边各个位置响应的元素,并且移动到响应的位置。

具体的实现代码如下:

$arr_count = count($rand_arr);
$index = 0;     //从左到右排序过程中起始的位置
$first_pos = 0; //从右到左排序过程中最后进行数据交换的位置
$up = $arr_count-1; //从左到右排序过程中结束的位置
$last_pos = $up; //从左到右排序过程中最后进行数据交换的位置
while($up >= $index){//从头开始扫描for($i=$index;$i<$up;$i++){if($rand_arr[$i]>$rand_arr[$i+1]){//进行交换$temp = $rand_arr[$i];$rand_arr[$i] = $rand_arr[$i+1];$rand_arr[$i+1] = $temp;$last_pos = $i;}}if($up == $last_pos){break;}$up = $last_pos;//从尾部开始扫描for($j=$up;$j>1;$j--){if($rand_arr[$j-1]>$rand_arr[$j]){//进行交换$temp = $rand_arr[$j];$rand_arr[$j] = $rand_arr[$j-1];$rand_arr[$j-1] = $temp;$first_pos = $j;}}if($index == $first_pos){break;}$index = $first_pos;
}

网上也有大神对这几种排序做了对比,用了1000个随机数组

没有进行优化,冒泡执行的时间38.826741201211
第一次优化后,冒泡执行的时间36.326452970505
第二次优化后,冒泡执行的时间24.916656017303
第三次优化后,冒泡执行的时间20.908751010895

【PHP】冒泡排序以及优化相关推荐

  1. 带哨兵的冒泡排序_冒泡排序的优化以及快排过程及优化

    冒泡排序的优化: 1.加入哨兵.2.记住每一次交换的最后位置,该位置以后的为有序,不需要改变. 1.快速排序的基本思想: 快速排序使用分治的思想,通过一趟排序将待排序列分割成两部分,其中一部分记录的关 ...

  2. Java的知识点18——数组存储表格数据、冒泡排序的基础算法、冒泡排序的优化算法、二分法查找

    数组存储表格数据 package cn.dym08; import java.util.Arrays; public class Test09 {public static void main(Str ...

  3. 十大经典排序算法之冒泡排序及其优化

    一.冒泡排序 1.冒泡排序算法的原理如下: 1.比较相邻的元素.如果第一个比第二个大,就交换他们两个. 2.对每一对相邻元素做同样的工作,从开始第一对到结尾的最后一对.在这一点,最后的元素应该会是最大 ...

  4. 排序算法:冒泡排序算法优化实现及分析

    冒泡排序算法介绍 冒泡排序(Bubble Sort)一种交换排序,它的基本思想是:两两比较相邻记录的关键字,如果反序则交换,直到没有反序记录为止.这是书上的定义,感觉太弯弯肠子了.冒泡排序是几乎所有学 ...

  5. java每轮排序结果,冒泡排序及其优化java

    java冒泡排序及其优化## version1 public static void bubbleSort() { int[] arr={5,6,1,4,3,2,7,8}: for (int i = ...

  6. C语言冒泡排序的优化(图解+代码)

    目录 1.常规的冒泡排序算法: 2.冒泡排序的优化: 1.常规的冒泡排序算法: 降序排列,小的数往下沉,大的数往上升: 升序排列,小的数在最上边,最大的数在最下边. 假设数组有n个数据,则无论最开始数 ...

  7. python 冒泡排序及优化_Python冒泡排序及优化

    一.冒泡排序简介 冒泡排序(Bubble Sort)是一种常见的排序算法,相对来说比较简单. 冒泡排序重复地走访需要排序的元素列表,依次比较两个相邻的元素,如果顺序(如从大到小或从小到大)错误就交换它 ...

  8. java 鸡尾酒排序_冒泡排序及优化(Java实现)

    向大端冒泡 public class BubbleSort { public static > void sort(T[] arr) { for (int i = 0, len = arr.le ...

  9. Java实现冒泡排序及其优化

    冒泡排序(Bubble Sort):从左至右(从下标较小的元素开始)依次比较相邻元素的值,若发现逆序则交换,使较大的元素逐渐从前移向后部. 冒泡排序的规则(以数组 arr= {3, 9, -1, 10 ...

  10. 数据结构与算法 / 冒泡排序及其优化的三种方式

    一.一般写法 统一使用交换函数: void swap(int& a, int& b) {int tmp = a;a = b;b = tmp;return; } void BubbleS ...

最新文章

  1. 数据库系列之数据管理(插入数据)
  2. 链计算:构建信任网络,致力无边界协同
  3. HDOJ1496 Equations【Hash】
  4. dll 共享_系统DLL查看和检测工具ListDLLs
  5. spring+redis自主实现分布式session(非spring-session方式)
  6. 小米平板5或无缘MIUI 13:搭配骁龙870 预装MIUI 12.5系统
  7. 如何保证高可用?java删除文件夹下所有文件,技术详细介绍
  8. VB里怎样使用GetWindowRect、GetClientRect、ScreenToClient、ClientToScreen
  9. java 微信网页授权_java微信网页授权获取openid(第十四课)
  10. 关于电脑突然产生数字文件夹用360删不掉的情况
  11. /deep/在chrome89+中出现样式混乱的问题
  12. 打麻将 - 基于R语言
  13. 2022天梯赛 L1-086 斯德哥尔摩火车上的题
  14. C语言自定义函数的声明
  15. 神、上帝以及老天爷(递推公式)
  16. EBS开发_创建AP付款
  17. 解决笔记本windows11充电后,屏幕亮度忽明忽暗的问题
  18. Swin Transformer全方位解读【ICCV2021马尔奖】
  19. IMX6ULL 主频和时钟配置
  20. 工程电磁场导论第一章总结

热门文章

  1. linux查看vnc进程命令_linux vncviewer使用ubuntu 关机命令
  2. [Store:280040]An invalid record was found in the store: Code=30
  3. 前端接modelmap的list_页面间传递前端请求参数和获取参数:Model model,HttpServletRequest request, ModelMap map参数使用与区别...
  4. 【有趣又简单的照片编辑器】PhotoScape X Pro for Mac 3.0
  5. 经典30句---四川话英语互译
  6. 敖丙大佬面试视屏学习(一)
  7. MySQL性能优化总结
  8. Mysql数据库高级、sql优化
  9. 从零开始的qplugin之——先弄弄图形
  10. uniapp使用支付宝芝麻信用免押