你必需要了解的幾種排序方法

  做爲一個程序員,你怎麼能不瞭解冒泡算法呢?javascript

  下面向你們介紹六中排序算法,並提供javascript實現,以及簡單分析算法複雜度。java

1. 簡單排序方法

1.1 冒泡排序

整體描述:
  相鄰元素進行比較,每次選取最大的元素,進行下一次比較,所以能夠將最大的元素像冒泡同樣,從某一位置,到達最頂端
算法簡單描述:
  假設:共有n個元素
  進行(n-1)次循環,第i(從1開始計數)次循環得到第i大的元素,放在數組第(n-i)(數組從0開始計數)位
每次循環都從第一個元素開始,比較當前元素與其後一個元素的大小關係,若是後一個元素小於當前元素,則說明,當前元素較大,互換位置,即將(0~n-i區間最大的數放在n-i位),並將當前元素指向下一個位置,直到當前位置指向0,循環結束程序員

完整代碼:算法

function bubbleSort(originArr) {
    /* 數組副本 */
    var cloneArr = originArr.concat();
    /* 用於交換數據 */
    var temp;
    /* 數組長度 */
    var len = cloneArr.length;

    /* 每次選擇出最大的元素 */
    /* 經過比較相鄰元素,將較大的元素放在後面,將較大的數繼續進行比較 */
    for (var i = 0; i < len - 1; ++i) { // 須要執行len-1次 for (var j = 0; j < len - i; ++j) { // 須要執行len-i-1次 // 若是當前元素大於下一個元素,互換兩個元素 
            if (cloneArr[j] > cloneArr[j + 1]) { // 執行(1 + 2 + ... + n-1)算法複雜度爲O(n^2)
                temp = cloneArr[j];
                cloneArr[j] = cloneArr[j + 1];
                cloneArr[j + 1] = temp;
            }
        }
    }

    return cloneArr;
}

1.2 選擇排序

整體描述:
  每次選擇最小的元素,放在相應的位置上
算法簡單描述:
  假設:共有n個元素
  進行(n-1)次循環,第i(從1開始計數)次循環得到第i小的元素,放在數組第(i-1)(數組從0開始計數)位,第i次循環,從數組第(i-1)位開始,將該位置元素與其後全部元素進行比較,獲取較小元素索引,循環結束以後,將當前元素與最小索引位置元素位置互換,當前位置向前移動,進行下一輪循環,直到當前位置指向(n-1)shell

完整代碼:數組

function selectionSort(originArr) {
    /* 數組副本 */
    var cloneArr = originArr.concat();
    /* 用於交換數據 */
    var temp;
    /* 存放最小元素索引 */
    var minIndex = 0;
    /* 數組長度 */
    var len = cloneArr.length;

    /* 從第一個位置開始,比較當前位置和後面全部元素,獲取最小元素後面的位置 */
    for (var i = 0; i < len - 1; ++i) { // 須要執行len-1次
        minIndex = i;
        // 獲取最小元素位置 
        for (var j = i + 1; j < len; ++j) { // 須要執行len-i-1次
            if (cloneArr[minIndex] > cloneArr[j]) { // 執行(1 + 2 + ... + n-1)算法複雜度爲O(n^2)
                minIndex = j;
            }
        }
        // 若是最小元素所在索引,不是當前位置,交換元素 
        if (minIndex !== i) {
            temp = cloneArr[i];
            cloneArr[i] = cloneArr[minIndex];
            cloneArr[minIndex] = temp;
        }
    }

    return cloneArr;
}

1.3 插入排序

整體描述:
  將數組分爲先後兩部分,前一部分是已排序的元素集合,後一部分是未排序的元素集合。每次選中未排序的第一個數組,插入到已排序集合中的合適的位置
算法簡單描述:
  假設:共有n個元素
  從第2個元素開始,進行(n-1)次循環,第i次循環,將第i個元素插入到以前位置(1~i-1)中,將當前元素依次後面元素進行比較。比較元素起始值爲當前元素前一位置元素,若是當前元素小於比較元素,比較元素向數組後面移動,當前元素繼續與下一個元素進行比較,直到比較元素位置爲0或者當前元素大於比較元素,將元素插入當前比較位置less

完整代碼:測試

function insertSort(originArr) {
    /* 數組副本 */
    var cloneArr = originArr.concat();
    /* 用於交換數據 */
    var temp;
    /* 數組長度 */
    var len = cloneArr.length;

    /* 循環數組中的每個元素 */
    for (var i = 1; i < len; ++i) { // 須要執行len-1次
        // 記錄要插入的值 
        temp = cloneArr[i];
        // 找到合適的位置插入 
        for (var j = i - 1; j >= 0; --j) { // 須要執行i次
            if (temp < cloneArr[j]) { // 執行(1 + 2 + ... + n-1)算法複雜度爲O(n^2)
                // 右移已排序數組 
                cloneArr[j + 1] = cloneArr[j];
            } else {
                break;
            }
        }
        cloneArr[j + 1] = temp;
    }

    return cloneArr;
}

2. 高級排序算法

2.1 希爾排序

整體描述:優化

  希爾排序就是插入排序的優化,插入排序,每次將當前元素與以前的每個元素進行比較,而後插入,希爾排序,至關於先按照必定步長,將數組進行分組,對每一組進行插入排序,這樣就能夠大幅度的調整數據的分佈狀況,最後執行一次快速排序進行微調
算法簡單描述:
  對於間隔數組中的每一個元素gap,將數組元素根據gap分爲gap組,對於每組進行插入排序ui

完整代碼:

function shellSort(originArr) {
    /* 數組副本 */
    var cloneArr = originArr.concat();
    /* 用於交換數據 */
    var temp;
    /* 數組長度 */
    var len = cloneArr.length;
    /* 間隔數組 */
    var gap = [];

    /* 動態建立間隔數組 */
    for (var i = Math.floor(len / 2); i > 0;) {
        gap.push(i);
        i = Math.floor(i / 2);
    }

    /* 使用間隔數組中的每個元素,選擇數組中的元素,進行快速排序 */
    /* 方法1: 對每個間隔的每個分組進行快速排序 */
    /*for (var i = 0, gapLen = gap.length; i < gapLen; ++i) {
        // 分爲gap[i]組分別進行排序 
        for (var j = 0; j < gap[i]; ++j) {
            // 第j組進行排序 
            for (var k = j + gap[i]; k < len; k = k + gap[i]) {
                temp = cloneArr[k];
                while (k - gap[i] >= 0 && cloneArr[k - gap[i]] > temp) {
                    cloneArr[k] = cloneArr[k - gap[i]];
                    k = k - gap[i];
                }
                cloneArr[k] = temp;
            }
        }
    }*/
    /* 方法2: 對於每個間隔,從間隔位置開始,對其後每個元素進行快速排序,保證前面的已經排好序 */
    for (var i = 0, gapLen = gap.length; i < gapLen; ++i) {
        for (var j = gap[i]; j < len; ++j) {
            temp = cloneArr[j];
            var k = j;
            while (k - gap[i] >= 0 && cloneArr[k - gap[i]] > temp) {
                cloneArr[k] = cloneArr[k - gap[i]]; 
                k -= gap[i];
            }
            cloneArr[k] = temp;
        }
    // 最壞狀況O(n(logn)^2) 平均狀況O(n(logn)^2) }
return cloneArr; }

2.2 快速排序

整體描述:
  每次選取一個基準值,將數組中其餘的元素和它進行比較,大於則移到數組右邊,小於則移到左邊。而後分類出來的數組繼續進行上述操做。
算法簡單描述:
  選擇數組第一位元素位基準值,建立兩個新數組,分別存放小於基準值和大於基準值的元素。而後這兩個新數組遞歸進行上述操做,直到數組爲空。而後將左右數組和基準值進行拼接

完整代碼:

function quickSort(originArr) {
    /* 若是數組爲空,直接返回 */
    if (originArr.length === 0) {
        return [];
    }

    /* 基準值 */
    var pivot = originArr[0];
    /* 分別存放大於小於數組 */
    var lesser = [];
    var greater = [];

    /* 小於基準值,存放到lesser數組中,不然存放到greater數組中 */
    for (var i = 1; i < originArr.length; ++i) {
        if (originArr[i] < pivot) {
            lesser.push(originArr[i]);
        } else {
            greater.push(originArr[i]);
        }
    // 最壞狀況O(n^2) 平均狀況O(nlogn) }
/* 將數組拼接後返回 */ return quickSort(lesser).concat(pivot, quickSort(greater)); }

2.3 歸併排序

整體描述:
  自頂向下:先經過遞歸分解數組,再合併數組
算法簡單描述:
  分解數組:若是數組長度不爲1,從中間將數組分爲兩部分,繼續分解
  合併數組:將分解的數組融合,建立一個新數組,用於存放融合的數組元素。建立指針分別指向兩個數組的首位,比較當前指針指向位置元素的大小,將較小的元素插入新數組中,指針向後移動,直到有一個數組元素所有移出。最後檢查兩個數組,將未移出的元素追加到新數組中,最後存放已排序的數組根據對應位置存入待排序數組中

完整代碼:

function mergeSort(originArr) {
    /* 數組副本 */
    var cloneArr = originArr.concat();

    /* 調用歸併排序 */
    doMergeSort(cloneArr, 0, cloneArr.length - 1);

    return cloneArr;
}

/* 向下分解數組,遞歸調用 */
function doMergeSort(arr, low, high) {
    if (low < high) {
        var mid = low + Math.floor((high - low) / 2);
        doMergeSort(arr, low, mid);
        doMergeSort(arr, mid + 1, high);
        merge(arr, low, mid, high);
    // 最壞狀況O(nlogn) 平均狀況O(nlogn) } }
/* 數組融合 */ function merge(arr, low, mid, high) { var p_low = low; var p_high = mid + 1; var sortArr = []; /* 比較左右部分元素,將較小的元素存放在sortArr前面 */ while (p_low <= mid && p_high <= high) { if (arr[p_low] > arr[p_high]) { sortArr.push(arr[p_high++]); } else { sortArr.push(arr[p_low++]); } } /* 將兩部分可能剩餘的元素複製到數組中 */ while (p_high <= high) { sortArr.push(arr[p_high++]); } while (p_low <= mid) { sortArr.push(arr[p_low++]); } /* 將已排序的數組複製到原數組對應位置 */ for (var i = low; i < high + 1; i++) { arr[i] = sortArr[i - low]; } }

3. 最終測試結果

100000數組測試:

相關文章
相關標籤/搜索