冒泡排序

Posted 某某雅

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了冒泡排序相关的知识,希望对你有一定的参考价值。

算法的思想

冒泡排序属于典型的交换排序。交换排序顾名思义就是通过元素的两两比较,判断是否符合要求,如过不符合就交换位置来达到排序的目的。冒泡排序名字的由来就是因为在交换过程中,类似水冒泡,小(大)的元素经过不断的交换由水底慢慢的浮到水的顶端

算法实现的具体思路

依次比较相邻的两个数,将比较小的数放在前面,比较大的数放在后面。

  • 第一次比较:首先比较第一个和第二个数,将小数放在前面,将大数放在后面。
  • 比较第2和第3个数,将小数 放在前面,大数放在后面。
    ......
  • 如此继续,直到比较到最后的两个数,将小数放在前面,大数放在后面,重复步骤,直至全部排序完成
  • 在上面一趟比较完成后,最后一个数一定是数组中最大的一个数,所以在比较第二趟的时候,最后一个数是不参加比较的。
  • 在第二趟比较完成后,倒数第二个数也一定是数组中倒数第二大数,所以在第三趟的比较中,最后两个数是不参与比较的。
  • 依次类推,每一趟比较次数减少依次

代码实现

  function bubbleSort(arr){
          for(let end = arr.length-1;end > 0;end--){ 
               for(let begin = 1;begin <= end; begin++){ //begin为什么要 <=end? 如果 bengin<end, 循环判断的时候就不会包含最后一项(end这一项)
                if(arr[begin] < arr[begin-1]){ // 让arr[begin] < arr[begin-1] 而不是arr[begin] <= arr[begin-1]的目的是维护算法的稳定性
                 //当比较两个相等的数值时我们需要保持两个相等的数值在原数组的位置
                 let temp = arr[begin];
                  arr[begin] = arr[begin-1];
                  arr[begin-1] = temp;
               }
           }
       }
       return arr;
   }

      let array=[8,94,15,88,55,76,21,39]
         let result = bubbleSort(array);
       console.log(result);

结果:

冒泡排序的时间复杂度与空间复杂度

  • 时间复杂度: 最好的时间: O(n)
    最坏时间: O(n2)
    平均时间: O(n2)
  • 空间复杂度: 没有用到额外的空间 1

优化问题

两个方向去考虑优化方面
第一种当数组刚好已经是完全排序好的,或者执行几遍就已经排序完成,上面的代码不论是否已经排序完成,会一直执行下去,这样会浪费很多时间。例如以下情况:

为了解决这个问题,我们可以设置一个标志位,用来表示当前第 i 趟是否有交换,如果有则要进行 i+1 趟,如果没有,则说明当前数组已经完成排序。实现代码如下:

     function bubbleSort(arr){
          for(let end = arr.length-1;end > 0;end--){
              let flag = true;
             for(let begin = 1;begin <= end; begin++){
                if(arr[begin] < arr[begin-1]){
                  let temp = arr[begin];
                  arr[begin] = arr[begin-1];
                  arr[begin-1] = temp;
                  flag = false;
               }
           }
               if(flag) break;
       }
       return arr;
   }

      let array=[8, 15, 21, 39, 55, 76, 88, 94]
         let result = bubbleSort(array);
       console.log(result);

另一种优化方式,如果数组的尾部已经局部有序了,这种情况完全可以记录最后一次交换的位置,下一次循环的结束条件可以是上一次循环记录的位置,这样就可以减少比较的次数。

代码如下所示

        function bubbleSort(arr){
          for(let end = arr.length-1;end > 0;end--){
              let flagIndex = 1; //flag不一定是1,可以是0,也可以是-1,只要能让数组是完全排序的情况下,循环可以直接退出循环就行
             for(let begin = 1;begin <= end; begin++){
                if(arr[begin] < arr[begin-1]){
                  let temp = arr[begin];
                  arr[begin] = arr[begin-1];
                  arr[begin-1] = temp;
                  flagIndex = begin; //记录一下每一次交换的位置
                  }
           }
               end = flagIndex;//将尾部已经局部有序的数值排除
       }
       return arr;
   }

      let array=[8, 15, 21, 39, 55, 76, 88, 94]
         let result = bubbleSort(array);
       console.log(result);

以上是关于冒泡排序的主要内容,如果未能解决你的问题,请参考以下文章

java冒泡排序法代码

python代码实现鸡尾酒排序(双向冒泡排序)

冒泡排序python代码

视频+图文+动画详解冒泡排序

交换排序(冒泡排序快速排序的算法思想及代码实现)

C语言冒泡排序。