写这篇文章源于之前的一次口试以及网上看到种种说原生的sort比快排快的例子,因为他们都没有写好快排。口试的时刻让我写一个快排,我写出了我在网上看的的很简约的一段代码(厥后发明这个代码在数据结构和算法JavaScript形貌这本书上也有):
function quickSort(arr){
if(arr.length < 1){
return [];
}
var left = [],right = [],flag = arr[0];
for(var i=1;i<arr.length;i++){
if(arr[i] <= flag){
left.push(arr[i]);
}else{
right.push(arr[i]);
}
}
return quickSort(left).concat(flag,quickSort(right));
}
如许写的话,乍一看确实是快排的头脑,把比主元小的元素放到左数组,把比主元大的元素放到右数组,然后分别对摆布数组的元素举行排序终究拼接成新的数组。
然则计算机课程里解说快排的时刻都不是如许解说的,一趟疾速排序的算法平常是如许解说的:
- 设置两个变量i、j,排序最先的时刻:i=0,j=N-1;
- 以第一个数组元素作为症结数据,赋值给key,即key=A[0];
- 从j最先向前搜刮,即由后最先向前搜刮(j–),找到第一个小于key的值A[j],将A[j]和A[i]交换;
- 从i最先向后搜刮,即由前最先向后搜刮(i++),找到第一个大于key的A[i],将A[i]和A[j]交换;
- 反复第3、4步,直到i=j;
采纳js完成的版本以下:
function quickSort_two(arr){
function sort(start,end){
if(start + 1 > end){
return;
}
var flag = arr[start],f = start,l = end;
while(f < l){
while(f < l && arr[l] > flag){
l--;
}
arr[f] = arr[l];
while(f < l && arr[f] <= flag){
f++;
}
arr[l] = arr[f];
}
arr[f] = flag;
sort(start,f-1);
sort(f+1,end);
}
sort(0,arr.length-1);
}
对照这两中快排的写法,在时候庞杂度上都是O(nlogn),然则第二种写法使用了更少的空间,第一种写法的空间庞杂度是O(nlogn),而第二种的空间庞杂度是O(logn),而且对数组的操纵都在原数组上举行,减去了建立空间的斲丧和时候,在性能上无疑有了更多的提拔。
下面是三种排序算法的一个对照:
function quickSort_one(arr){
if(arr.length < 1){
return [];
}
var left = [],right = [],flag = arr[0];
for(var i=1;i<arr.length;i++){
if(arr[i] <= flag){
left.push(arr[i]);
}else{
right.push(arr[i]);
}
}
return quickSort_one(left).concat(flag,quickSort_one(right));
}
function quickSort_two(arr){
function sort(start,end){
if(start + 1 > end){
return;
}
var flag = arr[start],f = start,l = end;
while(f < l){
while(f < l && arr[l] > flag){
l--;
}
arr[f] = arr[l];
while(f < l && arr[f] <= flag){
f++;
}
arr[l] = arr[f];
}
arr[f] = flag;
sort(start,f-1);
sort(f+1,end);
}
sort(0,arr.length-1);
}
function quickSort_three(arr){
arr.sort(function(a,b){
return a-b;
});
}
function countTime(fn,arr){
var start = Date.now();
fn(arr);
var end = Date.now();
console.log(end - start);
}
function randomVal(num){
var arr = [];
for(var i=0;i<num;i++){
arr.push(Math.ceil(Math.random()*num));
}
return arr;
}
在chrome下的一个运转状况(以100000个数为例,因为每次排序后数组都发生了转变,所以每次都建立了新数组,以100000的基数来算的话,虽然不是同一个数组,然则效果也是值得参考的):
在firefox下的运转效果:
不论是firefox照样chrome,第一种排序算法的时候都是最长的,第二种是最快的,原生的sort要领比第二种要领轻微慢一点,但比第一种照样快多了。