经典排序算法--冒泡排序

思路

对列表的无序部分从头至尾扫描一遍,扫描过程中通过不断交换相邻两个元素,最终把最大(小)元素交换到列表末尾。

  1. 首先比较第一和第二个数,把较大的放在第二位。
  2. 比较第二个和第三个数,再把较大的数放在第三位。
    … …
  3. 如此比较下去,直到比较完最后两个数。这样就把整个列表中最大的数交换到了末尾。
  4. 上面三步只是完成了对列表无序部分(一开始认为整个列表都是无序的)的一趟扫描,接下来我们将对列表剩下的无序部分按照上三步重复操作,每扫描一次都会把无序部分的最大值交换到排序部分的末尾,最终就会把所有元素按从小到大的顺序排列。

案例推演

排序无序数组 [10,1,35,61,89,36,55],案例来源于此博客

  1. 第一趟排序
    第一次比较:10 和1 比较,10大于1 ,两者交换位置,把10放1后面。 [1,10,35,61,89,36,55]
    第二次比较:10和35比较,10小于35,两者不交换位置。 [1,10,35,61,89,36,55]
    第三次比较:35和61比较,35小于61,两者不交换位置。 [1,10,35,61,89,36,55]
    第四次比较:61和89比较,61小于89,两者不交换位置。[1,10,35,61,89,36,55]
    第五次比较:89和36比较,89大于36,两者交换位置。 [1,10,35,61,36,89,55]
    第六次比较:89和55比较,89大于55,两者交换位置。[1,10,35,61,36,55,89]
    经过第一趟6次比较后成功将无序部分的最大元素89交换到了数组末尾。
  2. 第二趟排序
    接下来对剩下的6个无序元素按照上述比较规则重新排序,把它们当中的最大值61放到无序部分末尾(即数组倒数第二位)。
    … …
    依照此法排序,经过6趟排序后就可将此数组排序完成。下图展示了每扫描一遍数组无序部分后数组的整体情况:
    在这里插入图片描述
    结合整个排序过程,可以得到: 若 数 组 待 排 序 部 分 元 素 个 数 为 N , 则 将 其 排 序 完 毕 需 要 扫 描 N − 1 次 。 第 k 次 扫 描 时 需 要 比 较 相 邻 元 素 N − k 次 。 \color{red}若数组待排序部分元素个数为N,则将其排序完毕需要扫描N-1次。第k次扫描时需要比较相邻元素N-k次。 NN1kNk

代码实现

实现代码选择Scala语言。外层for循环控制扫描次数(N-1次),其取值范围为:[0,N-1),内层循环控制每次扫描时元素比较次数(N-k次),其取值范围为:[0,N-k)。

  def bubbleSort(array: Array[Int]): Unit = {
  // i 的取值范围是  [0,length-1)
    for (i <- 0 until array.length - 1) {
    // j取值范围是:[0, length - (i + 1)),
    // i + 1就是上文中的扫描次数k,这里i是从0开始计数,而k是从1开始计数,两者相差1
      for (j <- 0 until array.length - (i + 1)) {
      // 比较相邻元素,大的放后面
        if (array(j) > array(j + 1)) {
          val temp = array(j)
          array(j) = array(j + 1)
          array(j + 1) = temp
        }
      }
    }
  }

时间复杂度

排序一个有n个元素的无序数组,最坏情况下需要比较: (n-1)+(n-2)+…+1 = (n-1) *(n-1+1) / 2 次,所以时间复杂度为O(n^2)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值