快排

写这篇文章源于之前的一次口试以及网上看到种种说原生的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));
}

如许写的话,乍一看确实是快排的头脑,把比主元小的元素放到左数组,把比主元大的元素放到右数组,然后分别对摆布数组的元素举行排序终究拼接成新的数组。
然则计算机课程里解说快排的时刻都不是如许解说的,一趟疾速排序的算法平常是如许解说的:

  1. 设置两个变量i、j,排序最先的时刻:i=0,j=N-1;
  2. 以第一个数组元素作为症结数据,赋值给key,即key=A[0];
  3. 从j最先向前搜刮,即由后最先向前搜刮(j–),找到第一个小于key的值A[j],将A[j]和A[i]交换;
  4. 从i最先向后搜刮,即由前最先向后搜刮(i++),找到第一个大于key的A[i],将A[i]和A[j]交换;
  5. 反复第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要领比第二种要领轻微慢一点,但比第一种照样快多了。

    原文作者:yr1014
    原文地址: https://segmentfault.com/a/1190000009469304
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞