基本排序算法

基本排序算法

在計算機科學中,一個排序算法是一種能將一串數據依照特定的排列方式進行排列的一種算法。

這裏簡單的介紹三種最基本的排序,分別是:冒泡排序、選擇排序以及插入排序

排序的過程中,經常要用到交換元素位置,故抽離爲公共函數 swap

// 交換位置
export function swap(arr, index1, index2) {
    var temp = arr[index1];
    arr[index1] = arr[index2];
    arr[index2] = temp;
}

冒泡排序

冒泡排序是最簡單的排序,一一對比相鄰的兩個數,順序不對就交換過來,這樣子,每一輪最大的值總會慢慢的被交換到最右側。所以纔會叫冒泡排序

描述

假設數組長度爲 n

  • 比較相鄰的兩個數,如果第 1 個大於第 2 個,就交換位置
  • 重複第 1 步,一輪下來最大值被交換到第 n 個位置,也就是最右側
  • 開啓新一輪,重複 1~2 步,最大值會被冒泡到第 n-1 個位置
  • 重複上述步驟,直到所有都排序好

例子:

對 3, 1, 5, 2, 4 進行排序

1,3,5,2,4  3 > 1 ,交換位置
1,3,5,2,4  3 < 5 ,不變
1,3,2,5,4  5 > 2 ,交換位置
1,3,2,4,5  5 > 4 ,交換位置,第一輪結束
1,3,2,4,5  1 < 3 ,不變
1,2,3,4,5  3 > 2 ,交換位置
1,2,3,4,5  ...依次對比
1,2,3,4,5  ...
1,2,3,4,5  ... 結束

代碼實現

// 冒泡排序
export function bubbleSort(array) {
    for (let i = array.length - 1; i >= 1; i--) {
        let hasSwap = false;
        for (let j = 0; j <= i; j++) {
            if (array[j] > array[j + 1]) {
                swap(array, j, j + 1);
                hasSwap = true;
            }
        }
        if (!hasSwap) {
            // 這裏用於優化,如果某一輪之後,沒有進行任何交換,說明已經排序完成了,所以退出循環
            break;
        }
    }
}

效果演示

https://global.chen4342024.co...

注意打開開發者工具,切換到移動端模式

小結

冒泡算法是比較慢的排序之一,也是最容易實現的算法之一。

複雜度
  • 穩定性:穩定
  • 時間複雜度: 平均 O(n^2) 、 最壞 O(n^2) 、最好 O(n)
  • 額外空間複雜度 O(1)

選擇排序

選擇排序是指每一輪從數組中取出最小值,然後跟第一個元素交換位置。然後再找出第二個最小值,跟第二個元素交換位置,。。。以此類推。直到倒數第二個位置

例子

3, 1, 5, 2, 4 進行排序

// 這裏只展示每一輪的結果
3 1 5 2 4   //開始
1 3 5 2 4   //第 1 輪
1 2 5 3 4   //第 2 輪
1 2 3 5 4   //第 3 輪
1 2 3 4 5   //第 4 輪

代碼實現

// 選擇排序從開頭開始,找出最小的值,放在第一個位置
// 有點類似打撲克拍的時候,抽取每一張最小的放在最左邊
export function selectSort(array) {
    for (let i = 0; i < array.length - 1; i++) {
        let minIndex = i;
        let min = array[i];
        for (let j = i + 1; j < array.length; j++) {
            if (array[j] < min) {
                min = array[j];
                minIndex = j;
            }
        }
        swap(array, i, minIndex);
    }
}

效果演示

https://global.chen4342024.co...

注意打開開發者工具,切換到移動端模式
複雜度
  • 穩定性:不穩定
  • 時間複雜度: O(n^2)
  • 額外空間複雜度 O(1)

插入排序

插入排序的思想是,依次從數組中未排序的部分,取出數據,然後插入到已排序的部分。直到清空未排序的部分

描述

假設數組長度爲 n , 從第 2 項開始

  • 從第一個元素開始,該元素可以認爲已經被排序;
  • 取出下一個元素,在已經排序的元素序列中從後向前掃描;
  • 如果該元素大於新元素,將該元素移到下一位置;
  • 重複步驟 3,直到找到已排序的元素小於或者等於新元素的位置;
  • 將新元素插入到該位置後;
  • 重複步驟 2~5。

代碼實現

export function insertSort(array) {
    for (let i = 0; i < array.length; i++) {
        let temp = array[i];
        let j = i;
        while (j > 0 && array[j - 1] > temp) {
            // 將所有大於temp的往右移
            array[j] = array[j - 1];
            j--;
        }
        array[j] = temp;
    }
}

效果演示

https://global.chen4342024.co...

注意打開開發者工具,切換到移動端模式
複雜度
  • 穩定性:穩定
  • 時間複雜度:平均 O(n^2) 、 最壞 O(n^2) 、最好 O(n)
  • 額外空間複雜度 O(1)

效果演示(彙總)

https://global.chen4342024.co...

注意打開開發者工具,切換到移動端模式

總結

這三種最基本的排序算法的複雜度非常相似,從理論上來說,它們的執行效率也應該差不多。

在實際使用中,如果需要排序的數據比較多,是不推薦使用這 3 種排序的。畢竟他們的效率都不太理想

在實際應用中,應該選擇高級排序算法: 快速排序 ...

在隨機生成數據測試的時候,發現很多時候,插入排序要快於冒泡排序以及選擇排序。大概是冒泡/選擇排序的快 1 倍

這是因爲 插入排序需要比較的次數是 1+2+3+..+n = n * (n-1) /2,這是最壞的情況,大部分時候並不需要全部比較,所以平均下來只需要 n*(n-1)/4

而冒泡/選擇排序都需要n * (n-1)/2,所以平均下來,插入排序大概是冒泡/選擇排序的快 1 倍

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章