• 冒泡排序


    什么是冒泡排序(Bubble sort)

        要想学习排序算法,最好先从冒泡排序开始,这是最基础的排序算法。它是一种基础的交换排序。

        排序前的队列:

        

         排序后的队列期望结果:

         

        1、冒泡排序第一版

        冒泡排序的思想:把相邻的元素两两比较,当一个元素大于右侧相邻元素时,交换他们的位置;当一个元素小于右侧相邻元素时,位置不变。

        冒泡排序是一种稳定排序,值相等的元素并不会打算原本的顺序,由于改排序算法的每一轮都要遍历所有元素,总共遍历(元素数量-1)轮,所以时间复杂度为O(n²)。
        这里用PHP代码实现如下:
     1     /**
     2      * 冒泡排序的第一版
     3      * @param array $arr
     4      * @return array
     5      */
     6     public function bubbleSort(array $arr): array
     7     {
     8         $length = count($arr);
     9         for ($i = 0; $i < $length - 1; $i++) {
    10             for ($j = 0; $j < $length - $i - 1; $j++) {
    11                 if ($arr[$j] > $arr[$j + 1]) {
    12                     $temp = $arr[$j];
    13                     $arr[$j] = $arr[$j + 1];
    14                     $arr[$j + 1] = $temp;
    15                 }
    16             }
    17         }
    18         return $arr;
    19     }
       
         代码非常简单,使用双循环进行排序。外部循环控制所有的回合,内部循环实现每一轮的冒泡处理,先进行元素比较,再进行元素交换。
     
         2、 冒泡排序第二版:提前结束
     
          经过几轮的排序后,有可能整个数列已经是有序的了。但是按照排序算法,仍然要继续执行后面的排序。
     
          在这种情况下,如果能判断出数列已经有序,并做出标记,那么剩下的几轮排序就不必执行了,可以提前结束工作。
          优化后的算法,这里用PHP代码实现如下:      
     1     /**
     2      * 冒泡排序的第二版
     3      * @param array $arr
     4      * @return array
     5      */
     6     public function bubbleSort(array $arr): array
     7     {
     8         $length = count($arr);
     9 
    10         for ($i = 0; $i < $length - 1; $i++) {
    11             // 是否排序标识:如果没有交换,则列表已经完成排序
    12             $isSorted = false;
    13             for ($j = 0; $j < $length - $i - 1; $j++) {
    14                 if ($arr[$j] > $arr[$j + 1]) {
    15                     $temp = $arr[$j];
    16                     $arr[$j] = $arr[$j + 1];
    17                     $arr[$j + 1] = $temp;
    18                     $isSorted = true;
    19                 }
    20             }
    21 
    22             if (!$isSorted) {
    23                 break;
    24             }
    25         }
    26         return $arr;
    27     }

           3、 冒泡排序第三版:数列有序区的界定

            比如上图中这个数列:前半部分的元素(3,4,2,1)无序,后半部分的元素(5,6,7,8)按照升序排列,并且后半部分元素中的最小值也大于前半部分元素的最大值         

            第一轮排序后的结果:
             

               第二轮排序后的结果:

               

             分析:
             1)右面的许多元素已经是有序的了,可是每一轮还是白白地比较了许多次。这正是冒泡排序中另一个需要优化的点。
     
             2)这个问题的关键点在于对数列有序区的界定。按照现有的逻辑,有序区的长度和排序的轮数是相等的。例如第一轮排序过后的有序区长度是1,第2轮排序过后的有序长度是2......
         
             实际上,数列真正的有序区可能会大于这个长度,如上图第二轮排序后,后面的5个元素实际上都属于有序区了。因此后面的多次元素比较是没有意义的。那么,该如何避免这种情况呢?
     
             优化方案:我们可以在每一轮排序后,记录下来最后一次元素交换的位置,该位置即为无序数列的边界,再往后就是有序区了。

             优化的算法,这里用PHP代码实现如下:
     1     /**
     2      * 冒泡排序的第三种写法
     3      * @param array $arr
     4      * @return array
     5      */
     6     public function bubbleSort(array $arr): array
     7     {
     8         $length = count($arr);
     9 
    10         // 记录每一轮最后一次交换的下标
    11         $lastExchangeIndex = 0;
    12 
    13         // 无序数列的边界,每次比较只需要比到这里为止
    14         $sortBorder = $length - 1;
    15 
    16         for ($i = 0; $i < $length - 1; $i++) {
    17             // 是否排序标识:如果没有交换,则列表已经完成排序
    18             $isSorted = false;
    19 
    20             for ($j = 0; $j < $sortBorder; $j++) {
    21                 if ($arr[$j] > $arr[$j + 1]) {
    22                     $temp = $arr[$j];
    23                     $arr[$j] = $arr[$j + 1];
    24                     $arr[$j + 1] = $temp;
    25                     $isSorted = true;
    26 
    27                     // 更新为最后一次交换元素的位置
    28                     $lastExchangeIndex = $j;
    29                 }
    30             }
    31 
    32             // 更新无序数列的边界
    33             $sortBorder = $lastExchangeIndex;
    34 
    35             if (!$isSorted) {
    36                 break;
    37             }
    38         }
    39         return $arr;
    40     }
    41 }
       参考链接:https://visualgo.net/zh/sorting
  • 相关阅读:
    AFNetworking https (引用)
    UITextview 垂直居中
    通过经纬度计算两点间多距离
    iOS 状态机
    iOS 去掉table前面的空格
    ubuntu 更新系统时间
    Python 调用 C 语言 so
    转 iOS socket
    java正则表达式
    javascript小应用。
  • 原文地址:https://www.cnblogs.com/hld123/p/16211629.html
Copyright © 2020-2023  润新知