测试了一下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

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

posted @ 2011-08-27 17:27  Create Chen  阅读(...)  评论(...编辑  收藏