Learning LINQ: QuickSort
I took the plunge this afternoon and began studying LINQ, so far just mucking around with LINQ on collections. One of the first things I tried was to implement QSort.
Now -- ignoring the fact that I could just use an ORDERBY and that this is a very silly qsort implementation -- what I came up with was this:
public class lqsort
{
public static List<int> QSLinq(List<int> _items)
{
if (_items.Count <= 1)
return _items;
int _pivot = _items[0];
List<int> _less = (from _item in _items where _item < _pivot select _item).ToList();
List<int> _same = (from _item in _items where _item == _pivot select _item).ToList();
List<int> _greater = (from _item in _items where _item > _pivot select _item).ToList();
return (QSLinq(_less).Concat(_same.Concat(QSLinq(_greater)))).ToList();
}
}
The only thing that really bugs me is all of the casting involved. Are there any LINQ tricks I might use? Or am I just using LINQ for things it wasn't intended for?
Just change the type of the parameter to IEnumerable
and use the var
construct instead of your List<int>
for your local variables.
This will make your QSLinq
method better because it will accept more types of parameters, for example int[]
, as well as List<int>
.
See the new method:
public static IEnumerable<int> QSLinq(IEnumerable<int> _items)
{
if (_items.Count() <= 1)
return _items;
var _pivot = _items.First();
var _less = from _item in _items where _item < _pivot select _item;
var _same = from _item in _items where _item == _pivot select _item;
var _greater = from _item in _items where _item > _pivot select _item;
return QSLinq(_less).Concat(QSLinq(_same)).Concat(QSLinq(_greater));
}
Hope this helps.
Fun Question! This doesn't outperform OrderBy, but it does limit the repeated enumerations some.
public static IEnumerable<int> QSort2(IEnumerable<int> source)
{
if (!source.Any())
return source;
int first = source.First();
return source
.GroupBy(i => i.CompareTo(first))
.OrderBy(g => g.Key)
.SelectMany(g => g.Key == 0 ? g : QSort2(g));
}
I inadvertently generated a stackoverflow during development, as I QSorted when the Key == 0.
Just for fun I tested these solutions. I commited the cardinal performance testing sin (testing in debug mode), but I don't think that affects the big O effect we'll see. Here is the input (reversed input is worst case for quicksort)
IEnumerable<int> source = Enumerable.Range(0, 1000).Reverse().ToList();
How about this? (If I understand well you don't like the .ToList calls)
public static IEnumerable<int> QSLinq(IEnumerable<int> items)
{
if (items.Count() <= 1)
return items;
int pivot = items.First();
return QSLinq(items.Where(i => i < pivot))
.Concat(items.Where(i => i == pivot))
.Concat(QSLinq(items.Where(i => i > pivot)));
}
Disclaimer based on Jon answer: Do NOT use this algorithm in a real problem. It is very inefficient.
链接地址: http://www.djcxy.com/p/51326.html上一篇: 初学者指南LINQ
下一篇: 学习LINQ:QuickSort