小白的冒泡排序及优化方案| 8月更文挑战

前言

冒泡排序是我接触的第一种算法,最开始只是明白个大概,直到本身手写的时候才明白里面的思想,写下这篇文章,也是方便本身往后回顾。算法


介绍

用百度的话说:数组

冒泡排序(Bubble Sort),是一种计算机科学领域的较简单的排序算法。 它重复地走访过要排序的元素列,依次比较两个相邻的元素,若是顺序(如从大到小、首字母从Z到A)错误就把他们交换过来。走访元素的工做是重复地进行直到没有相邻元素须要交换,也就是说该元素列已经排序完成。 这个算法的名字由来是由于越小的元素会经由交换慢慢“浮”到数列的顶端(升序或降序排列),就如同碳酸饮料中二氧化碳的气泡最终会上浮到顶端同样,故名“冒泡排序”。markdown

用本身的话说:svn

冒泡排序是一种比较简单的排序算法,对数组进行升序排序时,会比较相邻元素,若是第一个元素大于第二个元素,就交换位置,不然就比较下两个元素。oop

[4,2,3,1]
使用冒泡排序,第一遍比较4和2,4>2,交换位置,获得
[2,4,3,1]
重复上一步,比较4和3,4>3,交换位置,获得
[2,3,4,1]
比较4和1,4>1,交换位置,获得
[2,3,1,4]
此时找到了数组中最大的元素4,以后重复上面的步骤去比较2和3...这里就很少作赘述。
在第一趟排序过程当中,4索引的变化:

  index:3
     ↑
  index:2
     ↑
  index:1
     ↑
  index:0

像是一个气泡不断上升且变大,故名冒泡排序
复制代码

代码实现

最简版性能

function bubble(arr) {
    let len = arr.length
    for(let i = 0 ; i < len; i ++) {
        // 当arr[j]为最后一个元素时,arr[j+1]不存在,没法比较,因此这里是j < len - 1
        for(let j = 0; j < len - 1; j ++) {
            console.log(`第一个元素:${arr[j]} 第二个元素:${arr[j+1]}`)
            if(arr[j] > arr[j + 1]) {
                [arr[j], arr[j + 1]] = [arr[j + 1], arr[j]]
            }
        }
        console.log(`=============================第${i+1}趟排序,结果为${arr}`)
    }
    return arr
}

console.log(bubble([4,2,3,1]))

// 第一个元素:4 第二个元素:2
// 第一个元素:4 第二个元素:3
// 第一个元素:4 第二个元素:1
// =============================第1趟排序,结果为2,3,1,4
// 第一个元素:2 第二个元素:3
// 第一个元素:3 第二个元素:1
// 第一个元素:3 第二个元素:4
// =============================第2趟排序,结果为2,1,3,4
// 第一个元素:2 第二个元素:1
// 第一个元素:2 第二个元素:3
// 第一个元素:3 第二个元素:4
// =============================第3趟排序,结果为1,2,3,4
// 第一个元素:1 第二个元素:2
// 第一个元素:2 第二个元素:3
// 第一个元素:3 第二个元素:4
// =============================第4趟排序,结果为1,2,3,4
// [ 1, 2, 3, 4 ]
复制代码

从输出结果来看,每趟遍历都要比较3次,但根据上面的冒泡原理可知,每遍历一次数组,就会找出最大/第二大/第三大...的数,因此上面的输出结果中,第2趟排序的3和4无需比较,由于第1趟排序已经能够确认4是最大的元素了。根据这个思路,优化方案flex

优化版v1优化

function bubble(arr) {
    let len = arr.length
    for(let i = 0 ; i < len; i ++) {
        // 注意这里,由于每遍历一次数组就能够找到最大的项,也就是说每遍历一次须要比较的元素就少一个
        for(let j = 0; j < len - 1 - i; j ++) {
            console.log(`第一个元素:${arr[j]} 第二个元素:${arr[j+1]}`)
            if(arr[j] > arr[j + 1]) {
                [arr[j], arr[j + 1]] = [arr[j + 1], arr[j]]
            }
        }
        console.log(`=============================第${i + 1}趟排序结束,结果为${arr}`)
    }
    return arr
}

console.log(bubble([4,2,3,1]))

// 第一个元素:4 第二个元素:2
// 第一个元素:4 第二个元素:3
// 第一个元素:4 第二个元素:1
// =============================第1趟排序结束,结果为2,3,1,4
// 第一个元素:2 第二个元素:3
// 第一个元素:3 第二个元素:1
// =============================第2趟排序结束,结果为2,1,3,4
// 第一个元素:2 第二个元素:1
// =============================第3趟排序结束,结果为1,2,3,4
// =============================第4趟排序结束,结果为1,2,3,4
// [ 1, 2, 3, 4 ]
复制代码

从上面代码能够看出,比较次数从原来的4趟12次变成了4趟6次,但仍是能发现,当第三躺排序结束的时候,其实已经完成排序了,但仍是进行了第4趟排序。咱们想要的是若是后面的元素都不须要比较(已是排序好的),则直接结束排序,根据这个思路,优化方案ui

优化版v2url

function bubble(arr) {
    let len = arr.length
    for (let i = 0; i < len; i++) {
        // 定义一个flag,表明后续元素是否须要交换位置
        let flag = true
        for (let j = 0; j < len - 1 - i; j++) {
            console.log(`第一个元素:${arr[j]} 第二个元素:${arr[j + 1]}`)
            if (arr[j] > arr[j + 1]) {
                // 须要交换位置,flag改成false
                flag = false;
                [arr[j], arr[j + 1]] = [arr[j + 1], arr[j]]
            }
        }
        // 若是`某次循环`中不须要交换位置,那么意味着排序已经完成,无需继续遍历
        if (flag) break;
        console.log(`=============================第${i + 1}趟排序结束,结果为${arr}`)
    }
    return arr
}

console.log(bubble([4, 2, 3, 1]))

// 第一个元素:4 第二个元素:2
// 第一个元素:4 第二个元素:3
// 第一个元素:4 第二个元素:1
// =============================第1趟排序结束,结果为2,3,1,4
// 第一个元素:2 第二个元素:3
// 第一个元素:3 第二个元素:1
// =============================第2趟排序结束,结果为2,1,3,4
// 第一个元素:2 第二个元素:1
// =============================第3趟排序结束,结果为1,2,3,4
// [ 1, 2, 3, 4 ]
复制代码

总结

冒泡排序的性能并不高,正常工做中也不经常使用,可是做为一种简单的排序方式,新手也能很容易理解。

相关文章
相关标签/搜索