冒泡排序

冒泡排序

 

 

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


 

1、原理

 每一趟只能确定将一个数归位。即第一趟只能确定将末位上的数归位,第二趟只能将倒数第 2 位上的数归位,依次类推下去。
 如果有 n 个数进行排序,只需将 n-1 个数归位,也就是要进行 n-1 趟操作。
 ​
 而 “每一趟 ” 都需要从第一位开始进行相邻的两个数的比较,将较大的数放后面,
 比较完毕之后向后挪一位继续比较下面两个相邻的两个数大小关系,重复此步骤,直到最后一个还没归位的数。 

 

2、动图演示

 

!>什么时候最快:当输入的数据已经是正序时(都已经是正序了,我还要你冒泡排序有何用啊)。

!>什么时候最慢:当输入的数据是反序时(写一个 for 循环反序输出数据不就行了,干嘛要用你冒泡排序呢,我是闲的吗)。


 

3、代码实现

3.1 JavaScript 代码实现

 function bubbleSort(arr) {
     var len = arr.length;
     for (var i = 0; i < len - 1; i++) {
         for (var j = 0; j < len - 1 - i; j++) {
             if (arr[j] > arr[j+1]) {        // 相邻元素两两对比
                 var temp = arr[j+1];        // 元素交换
                 arr[j+1] = arr[j];
                 arr[j] = temp;
             }
         }
     }
     return arr;
 }

 

3.2 Python 代码实现

 def bubbleSort(arr):
     for i in range(1, len(arr)):
         for j in range(0, len(arr)-i):
             if arr[j] > arr[j+1]:
                 arr[j], arr[j + 1] = arr[j + 1], arr[j]
     return arr

 

3.3 Go 代码实现

 func bubbleSort(arr []int) []int {
     length := len(arr)
     for i := 0; i < length; i++ {
         for j := 0; j < length-1-i; j++ {
             if arr[j] > arr[j+1] {
                 arr[j], arr[j+1] = arr[j+1], arr[j]
             }
         }
     }
     return arr
 }

 

3.4 Java 代码实现

 public static void BubbleSort(int [] arr){
      int temp;//临时变量
      for(int i=0; i<arr.length-1; i++){   //表示趟数,一共arr.length-1次。
          for(int j=arr.length-1; j>i; j--){
 ​
              if(arr[j] < arr[j-1]){
                  temp = arr[j];
                  arr[j] = arr[j-1];
                  arr[j-1] = temp;
              }
          }
      }
  }

 

4、优化(Java)

针对问题(1):

发现整个数列已经是有序的了 )– 数据的顺序排好之后,冒泡算法仍然会继续进行下一轮的比较,直到arr.length-1次,后面的比较没有意义的。

方案:

  • 设置标志位flag,如果发生了交换flag设置为true;如果没有交换就设置为false。

  • 这样当一轮比较结束后如果flag仍为false,即:这一轮没有发生交换,说明数据的顺序已经排好,没有必要继续进行下去。

 public static void BubbleSort1(int [] arr){
     if (arr == null || arr.length < 2) {
         return arr;
     }
     int temp;//临时变量
     boolean flag;//是否交换的标志
     for(int i=0; i<arr.length-1; i++){   //表示趟数,一共arr.length-1次。
         flag = true;
         for(int j=arr.length-1; j>i; j--){
             if(arr[j] < arr[j-1]){
                 temp = arr[j];
                 arr[j] = arr[j-1];
                 arr[j-1] = temp;
                 flag = false;//有元素交换,所以不是有序,标记变为false
             }
         }
         //一趟下来是否发生位置交换,如果没有交换直接跳出大循环
         if(flag) break;
     }
 }

 

针对问题(2):

发现整个数列有序区的界定 )– 数据的顺序排好之后, 在一轮排序后,发现后面其实又是有序数列了,但是还是要每一次两两相比,这样也白白比较了很多次了 。

图例:

方案:

  • 记录最后一次交换的位置

 public static int[] BubbleSort(int[] arr) {
      if (arr == null || arr.length < 2) {
           return arr;
      }
     //记录最后一次交换的位置
     int lastExchangeIndex = 0;
     //无序数列的边界,每次比较只需要比到这里为止
     int sortBorder = arr.length - 1;
     
     for (int i = 0; i < arr.length - 1; i++) {
          boolean isSorted  = true;//有序标记,每一轮的初始是true
          for (int j = 0; j < sortBorder; j++) {
              if (arr[j + 1] < arr[j]) {
                  isSorted  = false;//有元素交换,所以不是有序,标记变为false
                  int t = arr[j];
                  arr[j] = arr[j+1];
                  arr[j+1] = t;
                  lastExchangeIndex = j;
              }
          }
         sortBorder = lastExchangeIndex
          //一趟下来是否发生位置交换,如果没有交换直接跳出大循环
          if(isSorted )
               break;
      }
      return arr;
 }

 

posted @ 2022-04-20 17:21  梅子猪  阅读(16)  评论(0编辑  收藏  举报