此次優化排序算法呢是爲了在優先隊列中使用這個算法。算法
我從網絡上隨便複製一種排序算法,隨便找的,首先看看他的實現。數組
function Insertion(arr) {
let len = arr.length;
let preIndex, current;
for (let i = 1; i < len; i++) {
preIndex = i - 1;
current = arr[i];
while (preIndex >= 0 && current > arr[preIndex]) {
arr[preIndex + 1] = arr[preIndex];
preIndex--;
}
arr[preIndex + 1] = current;
}
return arr;
}
複製代碼
下面是測試隨機生成數組的函數:網絡
function randomArr(len, start, end) {
let arr = [];
while (arr.length < len) {
let d = Math.round(Math.random() * (end - start) + start);
arr.push(d);
}
return arr;
}
複製代碼
下面是測試函數,經過執行下面的函數能夠獲得對應的時間:dom
function test(n, start, end) {
console.time();
let a = randArr(n, start, end);
let b = Insertion(a);
console.timeEnd()
}
複製代碼
其中n
表明數組的個數,start
和end
表明數組的開始和結束,也就是區間。函數
下面是我優化後的函數:測試
function insertSort(arr = []) {
let sortArr = [];
// 當數組的長度小於2的時候
if (arr.length >= 2) {
if (arr[0] < arr[1]) {
sortArr.push(arr[1], arr[0]);
} else {
sortArr.push(arr[0], arr[1]);
}
} else {
sortArr.push(...arr);
}
for (let i = 2; i < arr.length; i++) {
let lPos = 0; // 左邊
let rPos = sortArr.length; // 右邊
let j = Math.floor((rPos - lPos) / 2);
while (rPos - lPos !== 1) {
if (arr[i] > sortArr[j]) {
rPos = j;
} else if (arr[i] < sortArr[j]) {
lPos = j;
} else {
lPos = j - 1;
rPos = j;
}
j = Math.floor((rPos + lPos) / 2); // j的值是這二者之間的值
}
if (arr[i] > sortArr[j]) { // 最後判斷與j位置的值,誰大誰小
sortArr.splice(j, 0, arr[i]); // 大則在當前位置插入
} else {
sortArr.splice(j + 1, 0, arr[i]);// 小則在下一個位置插入
}
}
return sortArr;
}
複製代碼
函數的實現比前一種要複雜一些。整體優化的思路在於第二層。也就是在找插入位置的時候我是經過二分搜索的方式進行的,這樣的時間負責度,差很少是nlogn級別的。跟前一種n^2級別要好一些,固然不能跟快速排序相提並論,之因此沒有選擇快速排序是由於快速排序的穩定性很差。而我要實現的優先隊列對穩定性要求高。優化
下面分別是10萬 - 50萬的測試結果,越到後面的數據次數越少(多條測試使用的逗號隔開的)。我這樣的對比並不是嚴格意義上的控制變量法,可是因爲我執行屢次獲得的結果幾乎類似,因此基本上能夠說明優化的效果。ui
// (100000數據量)
test(Insertion, 100000, 0, 10000); // 3.057, 3.101s, 3.072s, 3.078s
test(insertSort, 100000, 0, 10000);// 737.965ms, 764.219ms, 732.931ms, 739.714ms
複製代碼
// (200000數據量)
test(Insertion, 200000, 0, 10000); // [12.464s]
test(insertSort, 200000, 0, 10000);// [4.506s]
複製代碼
// (300000數據量)
test(Insertion, 300000, 0, 10000); // 27.746s,28.024s
test(insertSort, 300000, 0, 10000);// 10.432s,10.695s
複製代碼
// (400000數據量)
test(Insertion, 400000, 0, 10000); // 50.283s
test(insertSort, 400000, 0, 10000);// 16.581s
複製代碼
// (500000數據量)
test(Insertion, 500000, 0, 10000); // 1:18.815 (m:ss.mmm),1:19.075 (m:ss.mmm)
test(insertSort, 500000, 0, 10000);// 43.778s, 44.420s
複製代碼