При проверке возможностей LINQ я написал простую реализацию QuickSort и
был рад, что в конечном итоге функция быстрой сортировки помещается в одну строку.Однако я заметил, что производительность этой «однострочной» функции значительно отличается от моей первоначальной «прямой» версии.
Вот код, который вызывает функцию быстрой сортировки в цикле 10 раз:
var r = new Random(DateTime.Now.Millisecond);
Stopwatch watch = new Stopwatch();
for (int i = 0; i < 10; i++)
{
watch.Reset();
var randomA = new int[100].Select(x => r.Next(100)).ToList();
watch.Start();
var sorted = QuickSort<int>(randomA);
watch.Stop();
Console.WriteLine("Duration: {0} ms", watch.ElapsedMilliseconds);
}
Console.ReadLine();
И две реализации функции QuickSort с результатами вывода:
Простая версия:
IEnumerable<T> QuickSort<T>(IEnumerable<T> a) where T : IComparable<T>
{
if (a.Count() <= 1) return a;
var pivot = a.First();
IEnumerable<T> lesser = a.Skip(1).Where(x => x.CompareTo(pivot) < 0);
IEnumerable<T> bigger = a.Skip(1).Where(x => x.CompareTo(pivot) >= 0);
return QuickSort(lesser).Concat(new T[] { pivot }).Concat(QuickSort(bigger));
}
Выход Продолжительность: 22 мсПродолжительность: 3 мсПродолжительность: 3 мсПродолжительность: 3 мсПродолжительность: 3 мсПродолжительность: 3 мсПродолжительность: 2 мсПродолжительность: 2 мсПродолжительность: 3 мсПродолжительность: 3 мс
Реализация в одну строку:
IEnumerable<T> QuickSort<T>(IEnumerable<T> a) where T : IComparable<T>
{
return a.Count() <= 1 ? a :
QuickSort(a.Skip(1).Where(i => i.CompareTo(a.First()) < 0)).
Concat(new T[] { a.First() }).
Concat(QuickSort(a.Skip(1).Where(i => i.CompareTo(a.First()) >= 0)));
}
Выход Продолжительность: 24154 мсПродолжительность: 407 мсПродолжительность: 2281 мсПродолжительность: 2420 мсПродолжительность: 919 мсПродолжительность: 48777 мсПродолжительность: 4615 мсПродолжительность: 3115 мсПродолжительность: 1311 мсПродолжительность: 1631 мс
Почему такая большая разница в производительности?