原生JS數組sort()排序方法內部原理探究

sort()方法在原數組上進行排序,不生成副本(即會改變原數組) javascript

無參時的使用

此時排序的方式是按照ascii碼進行排序,它會先將數組裏的元素所有轉爲字符串(不影響原值),方便比較。java

let arr = [23, 12, 32, 5, 21, 7, 1]
    
arr.sort()
//此時原數組已經被改變
console.log(arr)
複製代碼

打印結果api

有參數時的使用

先看一下w3school所給的定義數組

這TM講的啥??a指代啥?b指的啥?內部用怎樣的方法實現的排序??接下來的就是咱們研究的重點
首先咱們來看一下a指代的究竟是什麼

let arr = [23, 12, 32, 5, 21, 7, 1]

console.log(arr)
arr.sort((a, b) => {
    console.log("a:" + a)
    return 1
})
console.log(arr)
複製代碼

打印結果dom

很容易看出a的範圍是 [arr[1],arr[arr.length-2]](爲了不偶然,我另外還作了許多測試,在這裏就不一一列舉了)
另外咱們還能看出當函數返回一個正值時,數組並無發生變化(0也是,這裏就不演示了)

接下來我麼再看一下b指的是什麼函數

let arr = [23, 12, 32, 5, 21, 7, 1]

console.log(arr)
arr.sort((a, b) => {
    console.log("b:" + b)
    return -1
})
console.log(arr)
複製代碼

打印結果性能

b的範圍 [arr[0],arr[arr.length-1]另外在這裏咱們還拾得一個使數組反序的方法(另一個是數組的 reverse()方法) a和b的範圍就這樣被咱們簡單的肯定了,但在真正排序的時候就不是這樣簡單了,咱們一塊兒來看一下吧

let arr = [23, 12, 32, 5, 21, 7, 1]

console.log(arr)
arr.sort((a, b) => {
    console.log("b:" + b)
    console.log("a:" + a)
    return a - b
})
console.log(arr)
複製代碼

打印結果 測試

驚不驚喜,意不意外??
別慌 咱們先把數據整理一下

到了這裏我就在猜測sort()內部有沒有多是 插入排序,因而我就開始了個人驗證

在這裏咱們證實了,sort()內部採用了 二分法插入排序,不過我在網上查閱的資料上說,若是數組的大小超過了10,就會採用快速排序的方法,咱們從下面的測試能夠側面推敲出這一結論

接下來比較一下sort排序和其餘排序的性能
sort()ui

let arr = []
for(let i = 0 ; i < 100000 ; i++){
    arr.push(parseInt(Math.random() * 10000))
}
//performance.now()H5的一個新的api,效果至關於Date.now(),不過它更強大
let startTime = performance.now()
arr.sort((a, b) => {
    return a - b
})
let endTime = performance.now()

console.log(endTime - startTime)
複製代碼

數值有波動,在這裏我取得使衆數,有興趣的小夥伴能夠本身測試 spa

快排

function quickSort(arr) {
    var len = arr.length;
    //結束遞歸的條件
    if (len <= 1) return arr;
    var left = [];
    var right = [];
    //中間基數
    var midindex = Math.floor(len / 2);
    var mid = arr[midindex];
    for (var i = 0; i < len; i++) {
        if (arr[i] == mid) continue;
        else if (arr[i] < mid) left.push(arr[i]);
        else right.push(arr[i]);
    }
    return quickSort(left).concat([mid], quickSort(right));
}

let arr = []
for(let i = 0 ; i < 100000 ; i++){
    arr.push(parseInt(Math.random() * 10000))
}

let startTime = performance.now()
quickSort(arr)
let endTime = performance.now()

console.log(endTime - startTime)
複製代碼

插入排序

function insertSort(arr) {
    var len = arr.length;
    for (var i = 0; i < len; i++) {
        var k = i;
        //前提: 1 前面必須有內容
        //前提: 2 當前這個元素,比左邊小,交換1次
        while (k - 1 >= 0 && arr[k] < arr[k - 1]) {
            var temp = arr[k];
            arr[k] = arr[k - 1];
            arr[k - 1] = temp;
            k--;
        }
    }
    return arr;
}

let arr = []
for(let i = 0 ; i < 100000 ; i++){
    arr.push(parseInt(Math.random() * 10000))
}

let startTime = performance.now()
insertSort(arr)
let endTime = performance.now()

console.log(endTime - startTime)
複製代碼

冒泡排序

let arr = []
for(let i = 0 ; i < 100000 ; i++){
    arr.push(parseInt(Math.random() * 10000))
}

function bubbleSort(arr) {
    var len = arr.length - 1;//循環次數
    for (var j = len; j > 0; j--) {
        //比較 交換
        for (var i = 0; i < j; i++) {
            if (arr[i] > arr[i + 1]) {
                var tamp = arr[i];
                arr[i] = arr[i + 1];
                arr[i + 1] = tamp;
            }
        }
    }
    return arr;
    }
let startTime = performance.now()
bubbleSort(arr)
let endTime = performance.now()

console.log(endTime - startTime)
複製代碼

總結

  1. sort()方法沒有參數時,按照ascii碼進行排序
  2. 經過給sort()的參數返回一個負值能夠實現數組reverse()效果
  3. sort(next,prev) 參數返回 next - prev時,數組是升序,返回-(next - prev)prev - next時,數組是降序
  4. 經過以上的比較咱們仍是能夠看出sort()方法效率仍是挺高的,能夠直接使用
  5. 通常狀況下,對數組進行排序使用快速排序或者sort(),在已知數據規律時才考慮其餘排序方式
相關文章
相關標籤/搜索