小白的冒泡排序及優化方案| 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 ]
複製代碼

總結

冒泡排序的性能並不高,正常工做中也不經常使用,可是做爲一種簡單的排序方式,新手也能很容易理解。

相關文章
相關標籤/搜索