用JavaScript實(shí)現(xiàn)常見(jiàn)的排序算法

前戲

  • 復(fù)習(xí)了一些比較常見(jiàn)的排序算法,用JS實(shí)現(xiàn),帶一些實(shí)現(xiàn)思路。
  • 無(wú)圖,無(wú)腦貼代碼。。

比較排序

冒泡排序

  1. 比較相鄰的元素,若第二個(gè)比第一個(gè)大,則交換位置。
  2. 對(duì)每一對(duì)相鄰元素作比較,一輪交換完成后,最大的元素應(yīng)該排在最后,即排序完成。
  3. 對(duì)剩余待排序元素重復(fù)步驟1~2,直到所有元素都已排序完成。
function bubbleSort(paramArr) {
    const arr = paramArr.slice()
    for (let i = 0; i < arr.length; i++) {
        for (let j = 0; j < arr.length - i; j++) {
            if (arr[j] > arr[j + 1]) {
                const temp = arr[j]
                arr[j] = arr[j + 1]
                arr[j + 1] = temp
            }
        }
    }
    return arr
}

選擇排序

  1. 從未排序序列中選擇最小的元素放在已排序序列的末尾。
  2. 重復(fù)步驟1,直到所有元素都已被放入已排序序列。
function selectionSort(paramArr) {
    const arr = paramArr.slice()
    for (let i = 0; i < arr.length; i++) {
        let minIndex = 0
        for (let j = 1; j < arr.length - i; j++) {
            if (arr[j] < arr[minIndex]) {
                minIndex = j
            }
        }
        arr.push(arr[minIndex])
        arr.splice(minIndex, 1)
    }
    return arr
}

插入排序

  1. 取出第一個(gè)元素,這個(gè)元素可以認(rèn)為已經(jīng)被排序。
  2. 取出下一個(gè)元素,從后向前依次對(duì)比,如果已排序元素大于新元素,則將該元素后移一位。
  3. 重復(fù)步驟2,直到找到已排序元素小于等于新元素的位置,將新元素插入。
  4. 重復(fù)步驟2~3,直到所有元素都插入完畢。
function insertionSort(paramArr) {
    const arr = paramArr.slice()
    for (let i = 1; i < arr.length; i++) {
        for (let j = i; j > 0; j--) {
            if (arr[j - 1] > arr[j]) {
                const temp = arr[j]
                arr[j] = arr[j - 1]
                arr[j - 1] = temp
            } else {
                break
            }
        }
    }
    return arr
}

快速排序

  1. 在待排序元素中選擇一個(gè)元素作為基準(zhǔn)。
  2. 將所有小于基準(zhǔn)的元素都移到基準(zhǔn)的左邊,所有大于基準(zhǔn)的元素都移到基準(zhǔn)的右邊。操作結(jié)束后,基準(zhǔn)就已經(jīng)處在最終排序后它的位置。
  3. 對(duì)左右兩個(gè)子集重復(fù)步驟1~2,直到所有的子集只剩下一個(gè)元素。

這里說(shuō)一下代碼細(xì)節(jié):

  1. 將序列中最后一個(gè)數(shù)作為基準(zhǔn)數(shù)。
  2. 用storeIndex表示移動(dòng)元素放置的位置,最開(kāi)始指向序列起點(diǎn)。
  3. 從前向后遍歷,移動(dòng)小于等于基準(zhǔn)元素的元素到數(shù)組的開(kāi)頭,每次移動(dòng) storeIndex 自增 1。
  4. 循環(huán)結(jié)束后將storeIndex位置上的元素與基準(zhǔn)數(shù)交換,此時(shí)一輪排序完成。
function quickSort(paramArr) {
    const swap = (arr, index1, index2) => {
        const temp = arr[index1]
        arr[index1] = arr[index2]
        arr[index2] = temp
    }

    const partition = (arr, start, end) => {
        let storeIndex = start
        const standardIndex = end
        for (let i = start; i < end; i++) {
            if (arr[i] <= arr[standardIndex]) {
                swap(arr, storeIndex, i)
                storeIndex += 1
            }
        }
        swap(arr, storeIndex, end)
        return storeIndex
    }

    const sort = (arr, start, end) => {
        if (start > end) return []
        const storeIndex = partition(arr, start, end)
        return [
            ...sort(arr, start, storeIndex - 1),
            arr[storeIndex],
            ...sort(arr, storeIndex + 1, end)
        ]
    }

    return sort(paramArr.slice(), 0, paramArr.length - 1)
}

非比較排序

計(jì)數(shù)排序

懶。。介紹就抄維基的啦。

  1. 找出待排序的數(shù)組中最大和最小的元素
  2. 統(tǒng)計(jì)數(shù)組中每個(gè)值為 i 的元素出現(xiàn)的次數(shù),存入數(shù)組 C 的第i項(xiàng)
  3. 對(duì)所有的計(jì)數(shù)累加(從 C 中的第一個(gè)元素開(kāi)始,每一項(xiàng)和前一項(xiàng)相加)
  4. 反向填充目標(biāo)數(shù)組:將每個(gè)元素i放在新數(shù)組的第 C[i] 項(xiàng),每放一個(gè)元素就將 C[i] 減去1
function countingSort(arr) {
    const bucketArr = []
    const sortedArr = []

    for (let i = 0; i < arr.length - 1; i++) {
        if (!bucketArr[arr[i]]) {
            bucketArr[arr[i]] = 1
        } else {
            bucketArr[arr[i]] += 1
        }
    }

    for (let i = 0; i < bucketArr.length - 1; i++) {
        if (bucketArr[i]) {
            for (let j = 0; j < bucketArr[i]; j++) {
                sortedArr.push(i)
            }
        }
    }

    return sortedArr
}

桶排序

  1. 設(shè)置一個(gè)定量的數(shù)組當(dāng)作空桶子。
  2. 尋訪序列,并且把項(xiàng)目一個(gè)一個(gè)放到對(duì)應(yīng)的桶子去。
  3. 對(duì)每個(gè)不是空的桶子進(jìn)行排序。
  4. 從不是空的桶子里把項(xiàng)目再放回原來(lái)的序列中。

這里對(duì)每個(gè)桶中的元素使用插入排序

function bucketSort(arr, step) {
    const bucket = []
    const sortedArr = []

    for (let i = 0; i < arr.length; i++) {
        const index = Math.floor(arr[i] / step)
        if (!bucket[index]) {
            bucket[index] = []
            bucket[index].push(arr[i])
        } else {
            bucket[index].push(arr[i])
            for (let j = bucket[index].length - 1; j > 0; j--) {
                if (bucket[index][j - 1] > bucket[index][j]) {
                    const temp = bucket[index][j]
                    bucket[index][j] = bucket[index][j - 1]
                    bucket[index][j - 1] = temp
                } else {
                    break
                }
            }
        }
    }

    for (let i = 0; i < bucket.length; i++) {
        if (bucket[i]) {
            for (let j = 0; j < bucket[i].length; j++) {
                sortedArr.push(bucket[i][j])
            }
        }
    }

    return sortedArr
}

結(jié)語(yǔ)

還有一些比較常見(jiàn)的如基數(shù)排序、堆排序這里沒(méi)有寫(xiě)(其實(shí)是已經(jīng)忘干凈了。??赡芤院髸?huì)再開(kāi)一篇吧)

慣例貼鏈接:

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 某次二面時(shí),面試官問(wèn)起Js排序問(wèn)題,吾絞盡腦汁回答了幾種,深感算法有很大的問(wèn)題,所以總計(jì)一下! 排序算法說(shuō)明 (1...
    流浪的先知閱讀 1,252評(píng)論 0 4
  • 概述 排序有內(nèi)部排序和外部排序,內(nèi)部排序是數(shù)據(jù)記錄在內(nèi)存中進(jìn)行排序,而外部排序是因排序的數(shù)據(jù)很大,一次不能容納全部...
    蟻前閱讀 5,297評(píng)論 0 52
  • 1、從瀏覽器地址欄輸入網(wǎng)址,到網(wǎng)頁(yè)徹底打開(kāi),中間都發(fā)生了什么 打開(kāi)網(wǎng)頁(yè)1,DNS域名解析2,TCP連接3,HTTP...
    idri閱讀 249評(píng)論 0 0

友情鏈接更多精彩內(nèi)容