Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/334.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/logging/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 学习LINQ:快速排序_C#_.net_Linq - Fatal编程技术网

C# 学习LINQ:快速排序

C# 学习LINQ:快速排序,c#,.net,linq,C#,.net,Linq,今天下午,我冒险开始研究LINQ,到目前为止,我只是在收集方面和LINQ混日子。我尝试的第一件事就是实现QSort 现在--忽略我可以使用ORDERBY的事实,这是一个非常愚蠢的qsort实现--我想到的是: public class lqsort { public static List<int> QSLinq(List<int> _items) { if (_items.Count <= 1) return

今天下午,我冒险开始研究LINQ,到目前为止,我只是在收集方面和LINQ混日子。我尝试的第一件事就是实现QSort

现在--忽略我可以使用ORDERBY的事实,这是一个非常愚蠢的qsort实现--我想到的是:

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();
    }
}
公共类lqsort
{
公共静态列表QSLinq(列表项)
{
如果(_items.Count _pivotselect _item).ToList();
return(QSLinq(_less).Concat(_same.Concat(QSLinq(_lever))).ToList();
}
}
唯一让我讨厌的是所有的演员阵容。我可能会使用LINQ技巧吗?还是我只是在用LINQ做它不打算做的事情?

这个怎么样?(如果我明白你不喜欢.ToList电话)

公共静态IEnumerable QSLinq(IEnumerable项)
{
if(items.Count()ii==pivot))
.Concat(QSLinq(items.Where(i=>i>pivot));
}

免责声明基于:不要在实际问题中使用此算法。效率很低。

所有涉及的铸件?我没有看到任何演员。我所看到的是对“ToList”的调用,这种调用效率极低。基本上,LINQ设计用于处理序列,这本质上不允许您以快速排序的方式就地(或在重复空间中)工作。基本上,这里有大量的数据复制:(

只需将参数类型更改为
IEnumerable
,并对局部变量使用
var
构造,而不是
列表

这将使
QSLinq
方法更好,因为它将接受更多类型的参数,例如
int[]
,以及
List

请参见新方法:

    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));
    }
公共静态IEnumerable QSLinq(IEnumerable\u项)
{
如果(_items.Count()_pivot选择_item;
返回QSLinq(_-less).Concat(QSLinq(_-same)).Concat(QSLinq(_-less));
}

希望这有帮助。

有趣的问题!这并没有比OrderBy更好,但它确实限制了一些重复枚举

    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));
    }
公共静态IEnumerable QSort2(IEnumerable源代码)
{
如果(!source.Any())
返回源;
int first=source.first();
返回源
.GroupBy(i=>i.CompareTo(第一))
.OrderBy(g=>g.Key)
.SelectMany(g=>g.Key==0?g:QSort2(g));
}
我在开发过程中无意中生成了一个stackoverflow,正如我在Key==0时所排序的那样


只是为了好玩,我测试了这些解决方案。我提交了基本性能测试sin(在调试模式下测试),但我认为这不会影响我们将看到的大O效应。以下是输入(反向输入是快速排序的最坏情况)

IEnumerable source=Enumerable.Range(0,1000).Reverse().ToList();
  • 解决方案花费了71000毫秒的三重concat
  • 我的解决方案耗时330毫秒
  • ToArray花费了15毫秒(计时器的分辨率,因此实际时间可能更少)

这里有另一个使用聚合的解决方案。我称之为:分组钓鱼。通过我的1000个反向元素测试,这一个需要170毫秒

    public static IEnumerable<int> QSort3(IEnumerable<int> source)
    {
        if (!source.Any())
            return source;
        int first = source.First();

        QSort3Helper myHelper = 
          source.GroupBy(i => i.CompareTo(first))
          .Aggregate(new QSort3Helper(), (a, g) =>
              {
                  if (g.Key == 0)
                      a.Same = g;
                  else if (g.Key == -1)
                      a.Less = g;
                  else if (g.Key == 1)
                      a.More = g;
                  return a;
              });
        IEnumerable<int> myResult = Enumerable.Empty<int>();
        if (myHelper.Less != null)
            myResult = myResult.Concat(QSort3(myHelper.Less));
        if (myHelper.Same != null)
            myResult = myResult.Concat(myHelper.Same);
        if (myHelper.More != null)
            myResult = myResult.Concat(QSort3(myHelper.More));

        return myResult;
    }

    public class QSort3Helper
    {
        public IEnumerable<int> Less;
        public IEnumerable<int> Same;
        public IEnumerable<int> More;
    }
公共静态IEnumerable QSort3(IEnumerable源代码)
{
如果(!source.Any())
返回源;
int first=source.first();
QSort3Helper myHelper=
source.GroupBy(i=>i.CompareTo(第一个))
.Aggregate(新的QSort3Helper(),(a,g)=>
{
如果(g.Key==0)
a、 相同=g;
else if(g.Key==-1)
a、 小于等于g;
else如果(g.Key==1)
a、 More=g;
返回a;
});
IEnumerable myResult=Enumerable.Empty();
if(myHelper.Less!=null)
myResult=myResult.Concat(QSort3(myHelper.Less));
if(myHelper.Same!=null)
myResult=myResult.Concat(myHelper.Same);
if(myHelper.More!=null)
myResult=myResult.Concat(QSort3(myHelper.More));
返回我的结果;
}
公共类QSort3Helper
{
公共资源的数量更少;
公共数字相同;
公营机构数目更多;
}

为什么这比我使用OrderBy的解决方案要快?我想它对最坏的情况有点抵抗力。

选择的答案是错误的,因为它包括QSLinq(_same)而不是在返回的集合中完全相同,并导致StackOverflowException。我将使用固定版本作为控件。如果解决方案可以使用复制,则速度可以大幅提高。使用线程而不是并行实际上会略微降低复制变体的性能。使用线程进行非复制g变体略微提高了性能。忽略了与控件的并行和非复制性能差异

最快复制:

private static List<int> quickie7(List<int> ites)
{
    if (ites.Count <= 1)
        return ites;
    var piv = ites[0];
    List<int> les = new List<int>();
    List<int> sam = new List<int>();
    List<int> mor = new List<int>();
    Enumerable.Range(0, 3).AsParallel().ForAll(i =>
    {
        switch (i)
        {
            case 0: les = (from _item in ites where _item < piv select _item).ToList(); break;
            case 1: sam = (from _item in ites where _item == piv select _item).ToList(); break;
            case 2: mor = (from _item in ites where _item > piv select _item).ToList(); break;
        }
    });
    var _les = new List<int>();
    var _mor = new List<int>();
    Enumerable.Range(0, 2).AsParallel().ForAll(i =>
    {
        switch (i)
        {
            case 0: _les = quickie7(les); break;
            case 1: _mor = quickie7(mor); break;
        }
    });
    List<int> allofem = new List<int>();
    allofem.AddRange(_les);
    allofem.AddRange(sam);
    allofem.AddRange(_mor);
    return allofem;
}
private static List quickie7(List ites)
{
如果(i)计数
{
开关(一)
{
案例0:les=(来自ites中的_项,其中_项piv选择_项);
}
});
var_les=新列表();
var_mor=新列表();
Enumerable.Range(0,2).AsParallel().ForAll(i=>
{
开关(一)
{
案例0:_les=quickie7(les);中断;
案例1:_mor=quickie7(mor);中断;
}
});
List allofem=新列表();
allofem.AddRange(_les);
allofem.AddRange(sam);
allofem.AddRange(_mor);
回归分析;
}
最快的非复制:

public static IEnumerable<int> QSLinq3(IEnumerable<int> _items)
{
    if (_items.Count() <= 1)
        return _items;
    var _pivot = _items.First();
    IEnumerable<int> _less = null;
    IEnumerable<int> _same = null;
    IEnumerable<int> _greater = null;
    ConcurrentBag<ManualResetEvent> finishes = new ConcurrentBag<ManualResetEvent>();
    Enumerable.Range(0, 3).AsParallel().ForAll(i =>
    {
        var fin = new ManualResetEvent(false);
        finishes.Add(fin);
        (new Thread(new ThreadStart(() =>
        {
            if (i == 0)
                _less = from _item in _items where _item < _pivot select _item;
            else if (i == 1)
                _same = from _item in _items where _item == _pivot select _item;
            else if (i == 2)
                _greater = from _item in _items where _item > _pivot select _item;
            fin.Set();
        }))).Start();
    });
    finishes.ToList().ForEach(k => k.WaitOne());
    return QSLinq(_less).Concat(_same).Concat(QSLinq(_greater));
}
公共静态IEnumerable QSLinq3(IEn
private static List<int> quickie7(List<int> ites)
{
    if (ites.Count <= 1)
        return ites;
    var piv = ites[0];
    List<int> les = new List<int>();
    List<int> sam = new List<int>();
    List<int> mor = new List<int>();
    Enumerable.Range(0, 3).AsParallel().ForAll(i =>
    {
        switch (i)
        {
            case 0: les = (from _item in ites where _item < piv select _item).ToList(); break;
            case 1: sam = (from _item in ites where _item == piv select _item).ToList(); break;
            case 2: mor = (from _item in ites where _item > piv select _item).ToList(); break;
        }
    });
    var _les = new List<int>();
    var _mor = new List<int>();
    Enumerable.Range(0, 2).AsParallel().ForAll(i =>
    {
        switch (i)
        {
            case 0: _les = quickie7(les); break;
            case 1: _mor = quickie7(mor); break;
        }
    });
    List<int> allofem = new List<int>();
    allofem.AddRange(_les);
    allofem.AddRange(sam);
    allofem.AddRange(_mor);
    return allofem;
}
public static IEnumerable<int> QSLinq3(IEnumerable<int> _items)
{
    if (_items.Count() <= 1)
        return _items;
    var _pivot = _items.First();
    IEnumerable<int> _less = null;
    IEnumerable<int> _same = null;
    IEnumerable<int> _greater = null;
    ConcurrentBag<ManualResetEvent> finishes = new ConcurrentBag<ManualResetEvent>();
    Enumerable.Range(0, 3).AsParallel().ForAll(i =>
    {
        var fin = new ManualResetEvent(false);
        finishes.Add(fin);
        (new Thread(new ThreadStart(() =>
        {
            if (i == 0)
                _less = from _item in _items where _item < _pivot select _item;
            else if (i == 1)
                _same = from _item in _items where _item == _pivot select _item;
            else if (i == 2)
                _greater = from _item in _items where _item > _pivot select _item;
            fin.Set();
        }))).Start();
    });
    finishes.ToList().ForEach(k => k.WaitOne());
    return QSLinq(_less).Concat(_same).Concat(QSLinq(_greater));
}