JavaScript實現(xiàn)合并(歸并)排序算法示例解析
JavaScript實現(xiàn)歸并排序算法詳解
說明
歸并排序(Merge Sort)算法,也叫合并排序,是創(chuàng)建在歸并操作上的一種有效的排序算法。算法是采用分治法(Divide and Conquer)的一個非常典型的應用,且各層分治遞歸可以同時進行。歸并排序思路簡單,速度僅次于快速排序,為穩(wěn)定排序算法,一般用于對總體無序,但是各子項相對有序的數(shù)列。
歸并排序和選擇排序一樣,歸并排序的性能不受輸入數(shù)據(jù)的影響,但表現(xiàn)比選擇排序好的多,因為始終都是O(n log n)的時間復雜度。代價是需要額外的內存空間。
歸并排序是用分治思想,分治模式在每一層遞歸上有三個步驟:
分解(Divide):將n個元素分成個含n/2個元素的子序列。
解決(Conquer):用合并排序法對兩個子序列遞歸的排序。
合并(Combine):合并兩個已排序的子序列已得到排序結果。
實現(xiàn)過程
- 將所有數(shù)組項無限細分,得到1個個獨立的單元,也就是不斷分解。
- 將相近的兩兩進行比較,按照已排序數(shù)組合并,形成(n/2)個序列,每個序列包含2個數(shù)字。
- 將上述兩個序列遞歸合并,按照已排序數(shù)組合并,形成(n/4)個序列,每個序列包含4個數(shù)字。
- 重復步驟2,直到所有元素合并排序完畢。
示意圖
性能分析
平均時間復雜度:O(nlogn)
最佳時間復雜度:O(n)
最差時間復雜度:O(nlogn)
空間復雜度:O(n)
排序方式:In-place
穩(wěn)定性:穩(wěn)定
JS第1種寫法,標準雙指針移動比較
/** * 歸并排序 ,采用分而治之(divide - conquer)的步驟 * 1. 分解(Divide),把待排序元素的序列分解為兩個子序列,以中間2分, 每個子序列包括一半成員。 * 2. 解決(Conquer),對每個子序列分別調用歸并操作, 進行遞歸或非遞歸循環(huán)操作,完成內部排序。 * 3. 合并(Combine),合并兩個排好序的子序列,生成排序結果。 歸并排序的最壞時間復雜度和平均時間復雜度均為O(nlogn) */ (function () { // 將兩個有序數(shù)組合并為一個新的有序數(shù)組 function merge (arr, left, mid, right) { // 先建立一個長度等于原數(shù)組的臨時數(shù)組 const temp = [] // 左側指針 let i = left // 右側指針 let j = mid + 1 // 臨時數(shù)組指針 let k = 0 // 當左指針小于中間,且右指針不大于最右側時 while (i <= mid && j <= right) { // 如果左側小于右側,將數(shù)移到臨時數(shù)組中左側 if (arr[i] <= arr[j]) { temp[k++] = arr[i++] // 否則移動到臨時數(shù)組右側 } else { temp[k++] = arr[j++] } } // 如果左邊數(shù)組還有數(shù)據(jù),就把左側剩余都放入到原數(shù)組后面 while (i <= mid) { temp[k++] = arr[i++] } // 如果右側數(shù)組還有數(shù)據(jù),把剩下的數(shù)據(jù)放入到原數(shù)組后面 while (j <= right) { temp[k++] = arr[j++] } // 將排序后的元素全部移動到原數(shù)組中 let x = 0 while (left <= right) { arr[left++] = temp[x++] } console.log('arr:', arr) } function mergeSort (arr, left, right) { // 得到中間值 const mid = Math.floor((left + right) / 2) // 如果左側小于右側則執(zhí)行合并排序 if (left < right) { // 遞歸合并左側 mergeSort(arr, left, mid) // 遞歸合并右側 mergeSort(arr, mid + 1, right) // 合并左右結果 merge(arr, left, mid, right) } return arr } // test const arr = [7, 11, 9, 10, 12, 13, 8, -2, 0, 8] console.time('sort') console.log('origin:', arr) console.log('\r\nsorted:', mergeSort(arr, 0, arr.length - 1)) console.timeEnd('sort') })();
JS第2種寫法,雙指針移動結合數(shù)組特性
(function () { function mergeSort (arr) { const len = arr.length if (len < 2) { return arr } // 取得當前數(shù)組的中間位置 const mid = Math.floor(len / 2) const left = arr.slice(0, mid) const right = arr.slice(mid) console.log('mergeSort arr:', arr, left, right) // 遞歸調用,不斷重復直到當前數(shù)組拆分剩1項 return merge(mergeSort(left), mergeSort(right)) } // 將兩個有序數(shù)組進行合并為一個新的有序數(shù)組 function merge (left, right) { // 建立一個空數(shù)組,用來存放排序結果 const result = [] // 左右數(shù)組的長度都不為空時,則將兩個數(shù)組的第一個進行比較 // 如左側小于右,則移除左側的內容到結果數(shù)據(jù),反之移動右側成員 while (left.length && right.length) { if (left[0] <= right[0]) { result.push(left.shift()) } else { result.push(right.shift()) } } // 最后把剩余的左或者右側成員全部添加到結果數(shù)組 while (left.length) { result.push(left.shift()) } while (right.length) { result.push(right.shift()) } // 這樣一趟下來后,兩個數(shù)組就合并為一個新的排序數(shù)組 return result } })()
鏈接
歸并排序算法源碼:https://github.com/microwind/algorithms/tree/master/sorts/mergesort
其他排序算法源碼:https://github.com/microwind/algorithms
以上就是JavaScript實現(xiàn)合并(歸并)排序算法示例解析的詳細內容,更多關于JavaScript合并(歸并)排序算法的資料請關注腳本之家其它相關文章!
相關文章
關于uniapp中onReachBottomDistance屬性的使用
這篇文章主要介紹了關于uniapp中onReachBottomDistance屬性的使用方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-09-09headjs實現(xiàn)網(wǎng)站并行加載但順序執(zhí)行JS
本文主要介紹如何使用head.js實現(xiàn)網(wǎng)站并行加載但順序執(zhí)行JS,提高網(wǎng)站加載速度。需要的朋友可以看下2016-11-11ztree獲取當前選中節(jié)點子節(jié)點id集合的方法
這篇文章主要介紹了ztree獲取當前選中節(jié)點子節(jié)點id集合的方法,實例分析了ztree的方法transformToArray使用技巧,需要的朋友可以參考下2015-02-02