JavaScript氣泡排序+Vue視覺化冒泡動畫

安木夕發表於2022-12-19

1.gif

氣泡排序(Bubble Sort)算是前端最簡單的演算法,也是最經典的排序演算法了。網上JavaScript版本的氣泡排序很多,今天用Vue實現一個動態的視覺化氣泡排序。

01、JavaScript氣泡排序

氣泡排序原理也比較簡單,就是相鄰元素兩兩比較排序,把大的元素氣泡排序到後面,遞迴所有相鄰元素組合完成排序。

1.1、原理

有一個無序陣列:let arr = [100, 5, 6, 17, 3, 1],長度為len=6

  • 、從第一位元素100(0索引)開始,比較相鄰arr[0]、arr[1]元素的大小,大的排後面,如果arr[0]>arr[1]則交換值位置。
  • 、如下圖,依次相鄰元素比較、交換,一輪完成後,最大元素就到了最右邊了。這個過程中,最大的元素(最大的泡泡)就像冒泡一樣到了末尾。

image

  • ③、然後繼續對剩下的前面len-1=5個元素重複上述步驟,直到只剩下一個元素。這是一個遞迴的過程,遞迴到第一個元素,就完成了氣泡排序。

image

氣泡排序的動畫過程如下圖,排序過程很直觀,一目瞭然,下一章節也實現一個跟好的。

1.2、JavaScript實現

經典氣泡排序演算法,用兩個for迴圈來實現所有元素的兩兩對比排序。統計了一下排序次數,一共比較了15次。氣泡排序的時間複雜度是O(n^2),這是最大值,最小為O(n)。

//經典氣泡排序演算法
//從小到大氣泡排序
let arr = [100, 5, 6, 17, 3, 1];
let count=0; //計數器
function bubbleSort(arr) {
    const len = arr.length;
    let t;count=0;
    for (let i = 0; i < len - 1; i++) {
        for (let j = 0; j < len - i - 1; j++) {
            count++;
            //比較相鄰兩個元素
            if (arr[j] > arr[j + 1]) {
                //交換兩個元素,大的往後排列
                t = arr[j];
                arr[j] = arr[j + 1];
                arr[j + 1] = t;
            }
        }
    }
    return arr;
}
console.log(bubbleSort(arr),"比較次數:",count);
//[1, 3, 5, 6, 17, 100] '比較次數:' 15

上面程式碼中交換兩個元素位置的時候,用了一箇中間變數(t),可以改進一下。用一個解構賦值來交換值,就不用額外的一箇中間變數(t)了。

let arr = [100, 5, 6, 17, 3, 1];
function bubbleSort(arr) {
    const len = arr.length;
    for (let i = 0; i < len - 1; i++) {
        for (let j = 0; j < len - i - 1; j++) {
            //比較相鄰兩個元素
            if (arr[j] > arr[j + 1]) {
                //用結構賦值進行交換
                [arr[j], arr[j + 1]] = [arr[j+1], arr[j]];
            }
        }
    }
    return arr;
}
console.log(bubbleSort(arr));
//[1, 3, 5, 6, 17, 100]

02、Vue實現一個冒泡動畫

用Vue來實現一個視覺化的氣泡排序,用Vue就不用去操作Dom了,只需要要處理好排序過程即可,因此首先要對排序過程進行改造。

2.1、排序過程改造

上一章節的排序是連續執行,瞬間完成的。要實現視覺化的排序效果,每一個排序步驟之間得有間隔,給過渡動畫留時間。就需要把排序的每一個步驟拆開,可以單獨控制執行。

  • 定義一個排序物件SortItem,包裝待排序元素,用於視覺化展示,屬性包括排序值、泡泡大小、泡泡顏色。
  • 用上面的排序物件SortItem,生成排序物件集合,正式排序步驟中用該集合。方法的引數為排序元素字串,空格隔開,如“9 100 6 17 3 1”。
//定義一個排序物件,包裝待排序元素
function SortItem(n) {
    this.value = n;
    this.size = 30 + n + 'px';  //泡泡大小,初試大小30px
    this.color = bubbleColor.default;
}
//生成排序物件集合,引數為排序元素字串,如“9 100 6 17 3 1”
function generateSortItems(arrStr) {
    let arrItems = [];
    let arr = arrStr.trim().split(' ');
    for (let i = 0; i < arr.length; i++) {
        arrItems[i] = new SortItem(window.parseInt(arr[i]));
    }
    return arrItems;
}

泡泡列表展示效果如下:

image.png

  • 然後就是排序過程了,對排序物件集合進行遍歷,把每一次排序操作包裝成一個(閉包)函式,放到一個集合裡,後面就可自定義呼叫執行了。
  • 先是用集合實現了一遍,發現這個場景用迭代器Generator更優雅,馬上重構,上迭代器!每次迭代yield返回排序的函式。
//迭代器實現排序步驟的拆分
function* generateSortFunc(items) {
  const len = items.length;
  for (let i = 0; i < len - 1; i++) {
    for (let j = 0; j < len - i - 1; j++) {
      //迭代器返回的是一個(閉包)函式,為每一個排序步驟
      yield () => {
        //執行排序前重置泡泡顏色
        resetColor(items);
        //正在排序的泡泡元素高亮
        items[j].color = bubbleColor.inprocess;
        items[j + 1].color = bubbleColor.inprocess;
        if (items[j].value > items[j + 1].value) {
          [items[j], items[j + 1]] = [items[j + 1], items[j]];
        }
      }
    }
    //完成一輪排序,末尾泡泡元素標記為完成態顏色
    items[len - i - 1].color = bubbleColor.completed;
  }
}

?什麼是Generator?

  • 她是一個迭代器,返回一個遍歷器物件,符合可迭代協議和迭代器協議,可用next()for(of)迭代。
  • 她是可控函式:內部程式碼可以自由控制暫停和繼續執行。標準的函式是一次性執行完畢,直到末尾或return語句。而生成器的函式可以由yield暫停執行(交出控制權),next()恢復執行。
  • 她是一個狀態機,封裝了多個內部狀態。
  • 她是非同步任務管理容器,提供一種非同步的實現方案。

Generator 使用一個特殊的函式語法function*(帶星*號)建立生成器generator,呼叫生成器函式獲得一個生成器物件,該物件的例項方法:

例項方法 描述
next() 恢復執行,返回一個由 yield表示式生成的值:{value: 1, done: false}
return(value?) 返回給定的值並結束生成器,可提前中止生成器。
throw() 向生成器丟擲一個錯誤,生成器內部如沒處理則會中止

2.2、視覺化排序

接下來就不難了,排序的執行就是呼叫執行器的next()方法,如果返回物件的done屬性為true,則表示迭代完成,否則繼續迭代,執行排序函式。

//單步執行
play() {
  let next = this.sortFunc.next();
  if (next.done) {
    this.sortItems.forEach(item => item.color = bubbleColor.completed);
    this.stop();
  }
  else
    next.value();
},
  • <li>元素來顯示排序物件。
  • 移動動畫用的Vue的<transition-group>元件來實現。
  • “單步執行”就是點選一次只執行一步,“自動執行”則會自動順序執行。
  • 修改引數後需”重置“進行初始化。

手動單步執行效果:

1.gif

自動執行或更多排序引數可以直接檢視線上程式碼示例:掘金-程式碼(視覺化冒泡),完整程式碼也在這裡。

點選檢視【juejin】


參考資料


©️版權申明:版權所有@安木夕,本文內容僅供學習,歡迎指正、交流,轉載請註明出處!原文編輯地址-語雀

相關文章