.net 4.5排序中的比较数

时间:2013-06-12 16:49:57

标签: c# sorting .net-4.0 .net-4.5

我知道4.5的排序算法从4.0改变了,但我怀疑内省排序的实现有问题。 似乎在反向排序列表的情况下行为不正常,当有人期望与“已排序”情况(如4.0中)相同数量的比较时,该数字奇怪地非常大。

.net 4 x64

随机25514058,分类20525265,反向20525285

.net 4.5 x64

随机22112103,排序16935357,逆转 31148728 !!

我用来获得比较次数的代码(使用4.0和4.5编译)是:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace sortTest {
class Program {
    class CmpCount : IComparer<int> {
        private int _count;
        /// <summary>
        /// 
        /// </summary>
        public int Count {
            get {
                return _count;
            }
        }



        public int Compare( int x, int y ) {
            _count++;
            return x.CompareTo( y );
        }
    }
    static void Main( string[] args ) {
        Random rnd = new Random(1234);
        List<int> list = new List<int>();
        for ( int i = 0; i < 1000000; i++ ) {
            list.Add( rnd.Next() );
        }
        CmpCount cmp = new CmpCount();
        list.Sort( cmp );
        int random = cmp.Count;

        cmp = new CmpCount();
        list.Sort( cmp );
        int sorted = cmp.Count;

        cmp = new CmpCount();
        list.Reverse();
        list.Sort( cmp );
        int reversed = cmp.Count;

        Console.WriteLine("random {0}, sorted {1}, reversed {2}",random,sorted,reversed);
    }
}
}

编辑:我正在调试源代码,似乎从未调用过HeapSort。也许它需要一个特殊的制作输入,这将触发它。实际上在上述情况下,4.5排序实际上只是快速排序。

快速查看源代码似乎4.0快速排序更复杂,而4.5是一个差(直接来自书籍?)实现。

如果我理解正确的话,4.5似乎也盲目地偏爱已排序的列表。这可能是反向排序列表的问题

1 个答案:

答案 0 :(得分:2)

introsort的.NET 4.5实现首先尝试执行Quicksort。当它看到递归深度超出特定点时,它会停止Quicksort并以Heap排序重新开始。

因此,期望进行大量比较并不是不合理的,因为算法正在进行部分排序,然后重新启动以进行完整排序。

此外,没有人知道.NET Quicksort如何选择要进行分区的项目。可能它使用的是中位数3.但它是否随机选择三个?第一,中,最后?对于两种相同的数组,分区可能不同(因此比较的数量可能不同)。

无论如何,Introsort并不声称自己是完美的。该算法很可能会检测到潜在的最坏情况,并切换到堆排序,即使使用快速排序会更快。 Introsort避免了最坏情况的行为,但有时可能表现出非最佳行为。

此外,无法保证您排序的阵列是相同的。您确定.NET 4和.NET 4.5之间的Random类实现没有改变吗? Random(1234)可能会在4.5上创建与4.0上不同的序列。如果是这样的话,你就不会比较同一阵列上的排序。