zoukankan      html  css  js  c++  java
  • 测试了一下LINQ写的Quick Sort性能

            昨晚看到一个帖子, 说的是三行代码实现快速排序, 文中实现Quick Sort代码如下:

    public static IEnumerable<T> QuickSort<T>(IEnumerable<T> list) where T : IComparable<T>
    {
        if (list.Count() <= 1) return list;
    
        var pivot = list.First();
    
        return QuickSort(list.Where(x => x.CompareTo(pivot) < 0))
                        .Concat(list.Where(x => x.CompareTo(pivot) == 0))
                        .Concat(QuickSort(list.Where(x => x.CompareTo(pivot) > 0)));
    }

            不由想起老赵两年前(正好整整两年天使)的一个帖子: 趣味编程:函数式链表的快速排序. 虽说在LINQ技术下, 三行代码是可以将快速排序的思路很直白明了的呈现出来, 这是函数式编程的优点. 看到这段代码里三个Where, 我心里不免有些疑问, Where不就枚举了整个链表了么, 这样做还是所谓的"Quick Sort"吗. 因此我用老赵的CodeTimer测试了一下它的性能, 并与传统的快速排序做个比较.

            传统的的Quick Sort算法摘自维基百科:

    public static void Sort(int[] numbers)
    {
        Sort(numbers, 0, numbers.Length - 1);
    }
    
    private static void Sort(int[] numbers, int left, int right)
    {
        if (left < right)
        {
            int middle = numbers[(left + right) / 2];
            int i = left - 1;
            int j = right + 1;
            while (true)
            {
                while (numbers[++i] < middle) ;
    
                while (numbers[--j] > middle) ;
    
                if (i >= j)
                    break;
    
                Swap(numbers, i, j);
            }
    
            Sort(numbers, left, i - 1);
            Sort(numbers, j + 1, right);
        }
    }
    
    private static void Swap(int[] numbers, int i, int j)
    {
        int number = numbers[i];
        numbers[i] = numbers[j];
        numbers[j] = number;
    }

            由于CodeTimer最后一个参数是一个Action委托, 我对两种快速排序算法包装了一下, 然后测试的时候就执行这两个方法:

    public static void FunctionalQuickSort()
    {
        int[] array = new int[] { 49, 38, 65, 97, 76, 13, 27 };
        QuickSort(array);
    }
    
    public static void NormalQuickSort()
    {
        int[] array = new int[] { 49, 38, 65, 97, 76, 13, 27 };
        Sort(array);
    }

            调用CodeTimer的Time方法, 就可以得到性能数据:

    //参数分别为: 输出的方法名字, 方法执行次数, 方法体
    CodeTimer.Time("Functional Quick Sort", 10000, () => FunctionalQuickSort());
    CodeTimer.Time("Normal Quick Sort", 10000, () => NormalQuickSort());

            做了几次测试, 得到的测试数据基本上是这个情况:

            这还只是7个数据的排序, 如果数据越多, 用LINQ写出来的算法性能劣势就越明显.

            另外我发现百度里讲解快速排序的算法过程真是坑爹, 我看了一下它那个过程, 觉得好像有点不对头, 自己在纸上又画了一遍, 真不明白它这句"此时再执行第三步的时候就发现 i=j, 从而结束一趟快速排序"是怎么来的...第一趟排序什么时候 i=j 过的...

    步骤序列ij
    0 49 38 65 97 76 13 27 0 6
    1 49 38 65 97 76 13 27 0 6
    2 27 38 65 97 76 13 49 2 6
    3 27 38 49 97 76 13 65 2 5
    4 27 38 13 97 76 49 65 3 5
    5 27 38 13 49 76 97 65 3 2

            由此看来, 一方面是简洁的书写代码, 另一方面是性能的考量, 您会选择哪种呢?

    作者:Create Chen
    出处:http://technology.cnblogs.com
    说明:文章为作者平时里的思考和练习,可能有不当之处,请博客园的园友们多提宝贵意见。
    知识共享许可协议本作品采用知识共享署名-非商业性使用-相同方式共享 2.5 中国大陆许可协议进行许可。

  • 相关阅读:
    Mysql主从同步延迟问题及解决方案
    elasticsearch 查询过程
    RPC(Remote Procedure Call):远程过程调用
    windows
    设计模式
    Linux Safe
    AS
    开机启动
    springboot打包部署
    【Linux】Linux 常用命令汇总
  • 原文地址:https://www.cnblogs.com/technology/p/2155666.html
Copyright © 2011-2022 走看看