算法图解三(快速排序及欧几里得)

226 阅读4分钟

快速排序——使用分而治之的策略

结论:

  • 分而治之:一种著名的递归式问题解决思想
  • 欧几里得算法:又名辗转相除法,一种常见且实用的算法思想
  • 欧几里得算法

    又名辗转相除法,是一种求最大公约数的常用方法

    方式:以较大数除以较小数,再用出现的余数(第一余数)去除除数,然后再用出现的余数(第二余数)去除第一余数,如此往复,直至余为0,最后的除数就是最大公约数

    A除B相当于说是用B除以A,即:B/A

注:比如说求(25,10)-> (25/10=2余5)-> (10/5=0余0)则最大公约数是整除全最后一个除数为5。


欧几里得算法用代码实现如下

    function Euclid(x, y) {
        let r = x > y ? x % y : y % x;
        let min = x > y ? y : x;
        if (r == 0) {
            return min;
        } else {
            return Euclid(min, r)
        }
    }
/**简化版本 */
    function Euclid(a, b) {
        return b === 0 ? a : Euclid(b, a % b);
    }
    Euclid(25, 10)//--5

使用递归函数进行数组之和/数组中最大值等获取

    function getSum(arr) {
        /*
        if(arr.length>1){
            //每次递归都移出数组第一项,*1避免字符串拼接而非运算
            return arr.shift()*1+getSum(arr)*1
        }else{
            return arr[0]
        }
        */
        //上方代码可简写成如下形式
        return arr.length == 1 ? arr[0] : arr.shift() + getSum(arr)
    }
    var arr = [2, 4, 5, 7, 5, 6, 2, 3]
    getSum(arr)

    function getMax(max, arr) {
        if (arr.length > 1) {
            //当前最大值大于数组当前首项则保持,否则重新赋值
            max = max > arr[0] ? max : arr[0];
            arr.shift()
            return getMax(max, arr)
        } else
            return max
    }
    var arr2 = [2, 4, 5, 7, 5, 6, 2, 3]
    getMax(0, arr2)

快速排序

1、算法的速度指的并非时间,而是操作数的增速。

2、谈论算法的速度时,说的是随着输入的增加,其运行时间将以什么样的速度增加。

3、算法的运行时间用大O表示法表示。

4、O(log n) 比 O(n)快,当需要搜索的元素越多时,前者比后者快得越多。

注:C语言标准库中得函数qsort实现的就是快速排序,快速排序也使用了D&C。

再谈大O表示法

  • 其中,快速排序的独特之处在于,它的速度取决于选择的基准值
  • 通常,用大O表示法是忽略会常量,常量对于一定大的数量级来说无关紧要
  • 来查看下常用算法的大O表示法
算法大O表示
二分查找O( logn )
简单查找O( n )
快速排序O(n logn )
选择排序O( n² )
旅行商问题算法O( n! )
  • 还有一种合并排序(merge sort)的排序算法,运行时间为O(nlogn)

在快速排序中

  • 快速排序由于性能依赖于选择的基准值
  • 因此,快排有平均情况和最糟情况之说
  • 情况一:
    • 若总是选择第一个元素作为基准值且处理的数组有序
    • 则此时的调用栈的高度为n,最糟情况调用栈的栈长为 O(n)
  • 情况二:
    • 若总是选择中间的元素为基准值
    • 则此时调用栈的高度为n/2,最佳情况调用栈的栈长为 O(logn)

因此最佳情况下,调用栈高度为O(logn),每层需要时间为O(n)该算法的运行时间为 O(logn)*O(n)=O(nlogn)

最糟糕情况下,调用栈高度为O(n),每层需要时间为O(n)该算法的运行时间为 O(n)*O(n)=O(n²)

注:最佳情况也是平均情况,快排的平均运行时间是 O(nlogn)

总结

由以上可知:

  • 实现随机排序时,请随机选择基准值元素,快排的平均运行时间为 O(nlogn)
  • 比较简单查找和二分查找时,常亮可以忽略不计,当列表很长时,O(logn) 的速度比 O(n) 快的多。

或许你对以下内容也感兴趣