此次优化排序算法呢是为了在优先队列中使用这个算法。算法
我从网络上随便复制一种排序算法,随便找的,首先看看他的实现。数组
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
复制代码