如下被稱爲分佈式排序的算法,原始數組中的數據會分發到多箇中間結構(桶),再合起來放回原始數組。最著名的分佈式算法有計數排序、桶排序和基數排序,這三種算法很是類似。算法
計數排序是一種用來排序整數的優秀算法,時間複雜度爲O(n + k),其中k是臨時計數數組的大小,可是,他須要更多的內存來存放臨時變量。typescript
export function sortArray(arr: Array<number>) { if (arr.length < 2){ return; } let len = findMaxNumber(arr) + 1; let countArr = new Array(len).fill(0); for (let i = 0; i < arr.length; i++) { countArr[arr[i]]++; } for (let i = 0,index = 0; i < countArr.length; i++) { for (let j = 0; j < countArr[i]; j++) { arr[index++] = i; } } } /** * 找最大數 * @param arr */ function findMaxNumber(arr: Array<number>):number { let max:number = 0; for (let i = 0; i < arr.length; i++) { if(arr[i] > max){ max = arr[i]; } } return max; } let arr = [54,8,45,7, 1,2,45,9,8,452,35,754,127,6,21,124,454] sortArray(arr) // @ts-ignore console.log(arr)
能夠看出這種排序很適合那種有多個重複數據的整數數組,可是數據中有一個特別大的時候,計數數組將會佔用很大的內存數組
還有這裏建立的數組是 最大值 + 1,由於數組的下標是0開始的,因此 +1確保最大值也能加入數據分佈式
桶排序
也稱之爲箱排序
,也是分佈式排序算法中的一種,它將元素分爲不一樣的桶(較小的數組),而後使用一個簡單的排序算法排序(好比說插入排序),而後合併數組爲結果code對於桶排序算法,咱們須要指定須要多少個桶來排序各個元素,默認狀況下,咱們會使用5個桶(這裏我認爲是每一個桶的容量爲5,並且看這個做者命名
bucketSize
,也以爲就是桶容量,不過肯定了一個桶的容量,天然就肯定了桶的個數,後面我仍是以桶容量來講明該參數)。桶排序在全部元素平分到各個桶時的表現最好。若是元素很是稀疏,則使用更多的桶會更好。若是元素很是密集,則使用較少的桶會比較好,所以咱們容許bucketSize
以參數的形式傳遞排序
第一步: 建立桶ip
建立桶看似很簡單,實際上仍是有點難度的,須要作到幾點內存
- 算出桶的個數:
Math.floor((最大值 - 最小值 ) / 單個桶的容量) + 1
- 而後建立一個
桶的個數
對應大小的數組,內部填充[]
,注意這裏不能使用fill
填充,fill
填充的數組是同一個引用,因此會致使失敗(這裏建立了一個二維數組)- 將排序元素塞到對應的桶裏去:
(當前值 - 最小值) / 單個桶的容量
,其實這個塞入的過程就已經對桶內數據進行了一次粗略排序
第二步: 對桶排序element
傳回的是一個二維數組,桶是有序的(0號桶的內容會都小於1號桶的內容)get
使用
插入排序
對桶內數據排序組合爲新的數組返回
import {sortArray as insertSort} from "./InsertSort" export function sortArray(arr: Array<number>, bucketSize: number = 5) { if (arr.length < 2) { return arr; } // 建立桶 let buckets = createBuckets(arr, bucketSize); // 桶排序並返回數組 return sortBuckets(buckets); } /** * 建立桶 * @param arr * @param bucketSize 單個桶的容量 */ function createBuckets(arr: Array<number>, bucketSize: number):any[][] { let minNum = arr[0]; let maxNum = arr[0]; // 循環查找最大值最小值 for (let i = 1; i < arr.length; i++) { if (maxNum < arr[i]) { maxNum = arr[i]; } else if (arr[i] < minNum) { minNum = arr[i]; } } // 計算桶數 const bucketCount = Math.floor((maxNum - minNum) / bucketSize) + 1; // 建立並初始化裝桶的數組,這裏就是一個二元數組了 const buckets = []; //這個for循環不要使用fill替換 for (let i = 0; i < bucketCount; i++) { buckets[i] = []; } for (let i = 0; i < arr.length; i++) { // 計算下標的過程實際上是對數據進行了一次簡單的排序,而後桶就會呈現出有序性 const index = Math.floor((arr[i] - minNum) / bucketSize) buckets[index].push(arr[i]); } return buckets; } /** * 對桶進行排序 * @param buckets */ function sortBuckets(buckets: any[][]) { let result = []; for (let i = 0; i < buckets.length; i++) { let element = buckets[i]; if(element !== null){ insertSort(element) result.push(...element); } } return result; } let arr = [54,8,45,7, 1,2,45,9,8,452,35,754,127,6,21,124,454] let sortArr = sortArray(arr) // @ts-ignore console.log(sortArr)
仍是想強調一下,填充桶數組的時候不能使用'fill'