中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

JavaScript中快速排序的案例

發布時間:2020-10-30 09:55:58 來源:億速云 閱讀:198 作者:小新 欄目:web開發

JavaScript中快速排序的案例?這個問題可能是我們日常學習或工作經常見到的。希望通過這個問題能讓你收獲頗深。下面是小編給大家帶來的參考內容,讓我們一起來看看吧!

介紹

排序是指以特定順序(數字或字母)排列線性表的元素。排序通常與搜索一起配合使用。

有許多排序算法,而迄今為止最快的算法之一是快速排序(Quicksort)

快速排序用分治策略對給定的列表元素進行排序。這意味著算法將問題分解為子問題,直到子問題變得足夠簡單可以直接解決為止。

從算法上講,這可以用遞歸或循環實現。但是對于這個問題,用遞歸法更為自然。

了解快速排序背后的邏輯

先看一下快速排序的工作原理:

  1. 在數組中選擇一個元素,這個元素被稱為基準(Pivot)。通常把數組中的第一個或最后一個元素作為基準。
  2. 然后,重新排列數組的元素,以使基準左側的有元素都小于基準,而右側的所有元素都大于基準。這一步稱為分區。如果一個元素等于基準,那么在哪一側都無關緊要。
  3. 針對基準的左側和右側分別重復這一過程,直到對數組完成排序。

接下來通過一個例子理解這些步驟。假設有一個含有未排序元素 [7, -2, 4, 1, 6, 5, 0, -4, 2] 的數組。選擇最后一個元素作為基準。數組的分解步驟如下圖所示:

JavaScript中快速排序的案例

在算法的步驟1中被選為基準的元素帶顏色。分區后,基準元素始終處于數組中的正確位置。

黑色粗體邊框的數組表示該特定遞歸分支結束時的樣子,最后得到的數組只包含一個元素。

最后可以看到該算法的結果排序。

用 JavaScript 實現快速排序

這一算法的主干是“分區”步驟。無論用遞歸還是循環的方法,這個步驟都是一樣的。

正是因為這個特點,首先編寫為數組分區的代碼 partition()

function partition(arr, start, end){
    // 以最后一個元素為基準
    const pivotValue = arr[end];
    let pivotIndex = start; 
    for (let i = start; i < end; i++) {
        if (arr[i] < pivotValue) {
        // 交換元素
        [arr[i], arr[pivotIndex]] = [arr[pivotIndex], arr[i]];
        // 移動到下一個元素
        pivotIndex++;
        }
    }
    
    // 把基準值放在中間
    [arr[pivotIndex], arr[end]] = [arr[end], arr[pivotIndex]] 
    return pivotIndex;
};

代碼以最后一個元素為基準,用變量 pivotIndex 來跟蹤“中間”位置,這個位置左側的所有元素都比 pivotValue 小,而右側的元素都比 pivotValue 大。

最后一步把基準(最后一個元素)與 pivotIndex 交換。

遞歸實現

在實現了 partition() 函數之后,我們必須遞歸地解決這個問題,并應用分區邏輯以完成其余步驟:

function quickSortRecursive(arr, start, end) {
    // 終止條件
    if (start >= end) {
        return;
    }
    
    // 返回 pivotIndex
    let index = partition(arr, start, end);
    
    // 將相同的邏輯遞歸地用于左右子數組
    quickSort(arr, start, index - 1);
    quickSort(arr, index + 1, end);
}

在這個函數中首先對數組進行分區,之后對左右兩個子數組進行分區。只要這個函數收到一個不為空或有多個元素的數組,則將重復該過程。

空數組和僅包含一個元素的數組被視為已排序。

最后用下面的例子進行測試:

array = [7, -2, 4, 1, 6, 5, 0, -4, 2]
quickSortRecursive(array, 0, array.length - 1)

console.log(array)

輸出:

-4,-2,0,1,2,4,5,6,7
循環實現

快速排序的遞歸方法更加直觀。但是用循環實現快速排序是一個相對常見的面試題。

與大多數的遞歸到循環的轉換方案一樣,最先想到的是用棧來模擬遞歸調用。這樣做可以重用一些我們熟悉的遞歸邏輯,并在循環中使用。

我們需要一種跟蹤剩下的未排序子數組的方法。一種方法是簡單地把“成對”的元素保留在堆棧中,用來表示給定未排序子數組的 startend

JavaScript 沒有顯式的棧數據結構,但是數組支持 push()pop() 函數。但是不支持 peek()函數,所以必須用 stack [stack.length-1] 手動檢查棧頂。

我們將使用與遞歸方法相同的“分區”功能。看看如何編寫Quicksort部分:

function quickSortIterative(arr) {
    // 用push()和pop()函數創建一個將作為棧使用的數組
    stack = [];
    
    // 將整個初始數組做為“未排序的子數組”
    stack.push(0);
    stack.push(arr.length - 1);
    
    // 沒有顯式的peek()函數
    // 只要存在未排序的子數組,就重復循環
    while(stack[stack.length - 1] >= 0){
        
        // 提取頂部未排序的子數組
        end = stack.pop();
        start = stack.pop();
        
        pivotIndex = partition(arr, start, end);
        
        // 如果基準的左側有未排序的元素,
        // 則將該子數組添加到棧中,以便稍后對其進行排序
        if (pivotIndex - 1 > start){
            stack.push(start);
            stack.push(pivotIndex - 1);
        }
        
        // 如果基準的右側有未排序的元素,
        // 則將該子數組添加到棧中,以便稍后對其進行排序
        if (pivotIndex + 1 < end){
            stack.push(pivotIndex + 1);
            stack.push(end);
        }
    }
}

以下是測試代碼:

ourArray = [7, -2, 4, 1, 6, 5, 0, -4, 2]
quickSortIterative(ourArray)

console.log(ourArray)

輸出:

-4,-2,0,1,2,4,5,6,7

可視化演示

當涉及到排序算法時,將其可視化能幫我們直觀的了解它們是怎樣運作的,下面這個例子搬運自維基百科:

JavaScript中快速排序的案例

在圖中也把最后一個元素作為基準。給定數組分區后,遞歸遍歷左側,直到將其完全排序為止。然后對右側進行排序。

快速排序的效率

現在討論它的時間和空間復雜度。快速排序在最壞情況下的時間復雜度是 $O(n^2)$。平均時間復雜度為 $O(n\log n)$。通常,使用隨機版本的快速排序可以避免最壞的情況。

快速排序算法的弱點是基準的選擇。每選擇一次錯誤的基準(大于或小于大多數元素的基準)都會帶來最壞的時間復雜度。在重復選擇基準時,如果元素值小于或大于該元素的基準時,時間復雜度為 $O(n\log n)$。

根據經驗可以觀察到,無論采用哪種數據基準選擇策略,快速排序的時間復雜度都傾向于具有 $O(n\log n)$ 。

快速排序不會占用任何額外的空間(不包括為遞歸調用保留的空間)。這種算法被稱為in-place算法,不需要額外的空間。

感謝各位的閱讀!看完上述內容,你們對JavaScript中快速排序的案例大概了解了嗎?希望文章內容對大家有所幫助。如果想了解更多相關文章內容,歡迎關注億速云行業資訊頻道。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

佛教| 长治市| 郧西县| 灵丘县| 西盟| 汾阳市| 固始县| 成武县| 海口市| 玉环县| 建平县| 巴青县| 嘉善县| 平谷区| 玉林市| 巨鹿县| 宣恩县| 凤庆县| 黎城县| 乐平市| 大理市| 多伦县| 嘉禾县| 徐闻县| 增城市| 阿拉善盟| 吉安县| 延边| 哈尔滨市| 阳信县| 湘潭市| 怀宁县| 邹城市| 南丹县| 昌邑市| 靖安县| 嘉定区| 榆中县| 云梦县| 巴彦淖尔市| 万州区|