【问题标题】:List Operations without ForLoops列出没有 For 循环的操作
【发布时间】:2011-08-24 00:23:13
【问题描述】:

我的班级有以下成员:

  • X
  • 宽度
  • 身高

可以使用这些参数创建一个矩形。

现在我的问题是我有一个此类的列表,List<MyClass>

我需要将列表中的每个对象与所有剩余对象进行比较,如果currentObject.Location(X, Y) 落在另一个对象的rectangle(X, Y, Width, Height) 中,我需要从列表中删除另一个对象。

我用 for 循环实现了它。

但主要问题是:性能。 我的最小列表数是 300000。

是否有任何程序可以使用任何 .Net 版本(包括 LINQ)来提高此任务的性能?

`公共类 RectBase { 私人 int _rectId; 私人PointF _rectLocation; 私有SizeF _rectSize;

    public RectBase()
    {
        _rectId = -911;
        _rectLocation = new PointF(0, 0);
        _rectSize = new SizeF(0, 0);
    }
    public RectBase(int id, PointF loc, SizeF size)
    {
        _rectId = id;
        _rectLocation = loc;
        _rectSize = size;
    }
    public bool IsIntersected(RectBase otherRectObject)
    {
        RectangleF currentRect = new RectangleF(_rectLocation, _rectSize);
        if (currentRect.Contains(otherRectObject.RectLocation))
            return true;
        else
            return false;
    }
    public int RectId
    {
        get { return _rectId; }
        set { _rectId = value; }
    }
    public PointF RectLocation
    {
        get { return _rectLocation; }
        set { _rectLocation = value; }
    }
    public SizeF RectSize
    {
        get { return _rectSize; }
        set { _rectSize = value; }
    }
}


public class RectProcessor
{
    List<RectBase> _rectList;
    int maxCount = 300000;

    public RectProcessor()
    {
        _rectList = new List<RectBase>();
        FillList();
    }

    private void FillList()
    {
        //  Adding the items to the list with dummy values
        for (int i = 0; i < maxCount; i++)
        {
            int id = i+1;
            PointF loc = new PointF(id, id);
            SizeF sz = new SizeF(id, id);

            RectBase obj = new RectBase(id, loc, sz);

            _rectList.Add(obj);
        }
    }

    private void RemoveIntersectedObjects()
    {
        List<RectBase> filteredList = new List<RectBase>();
        bool isIntersected = false;

        for (int i = 0; i < maxCount; i++)
        {
            for (int j = 0; j < maxCount; j++)
            {
                if (_rectList[i].IsIntersected(_rectList[j]))
                {
                    isIntersected = true;
                    break;
                }
            }
            if (!isIntersected)
            {
                filteredList.Add(_rectList[i]); 
            }
            isIntersected = false;
        }
    }
}

`

【问题讨论】:

  • 感觉四叉树可以帮到你...
  • 请发布代码示例,以便我们了解您是如何解决问题的。
  • Linq 不会更快。您需要的是针对该问题的优化算法。
  • 听起来矩形的顺序很重要 - “对于所有 R[i = 0..n] 和所有 R[j = i+1..n] 如果 R[i]重叠 R[j] 然后删除 R[i]。”如果是这样的话,那么我认为你被卡住了。任何形式的问题划分都会影响矩形的顺序,因此会删除错误的。您可以获得的最佳性能是对n 矩形的n*(n-1)/2 操作。
  • 这是对问题的正确陈述吗:“给定一个矩形列表,从列表中删除完全包含在列表中任何其他矩形边界内的任何矩形。”?

标签: c# .net linq list


【解决方案1】:

问题不在于消除for 循环,至少在您的想法上是这样。在 LINQ 中重写它只会隐藏 for 循环,但它们仍然会存在。这就是根本问题。你写的算法是O(n^2),这就是为什么当你从 20,000 个元素增加到 300,000 个元素时,你会看到一个荒谬的时间爆炸。您在第一种情况下进行了 400,000,000 次比较,在第二种情况下进行了 90,000,000,000 次比较,并且它将像 O(n^2) 一样继续增长。

那么,你真正想问的问题是:对于这个问题,有没有一种时间复杂度比O(n^2) 更好的算法?

坦率地说,我不知道这个问题的答案。我怀疑答案是否定的:如果不将某个点与所有矩形进行比较,您就无法知道某个点是否包含在某个矩形中,并且您必须检查所有点。但也许有一个聪明的方法来做到这一点,比如计算所有矩形的凸包并以某种方式使用它?

这个问题是computational geometry字段的一个例子。

【讨论】:

  • 没错。我需要用更少的时间消除重复项。换句话说,我希望修改 RemoveIntersectedObjects 方法。
  • 我的第一个想法是遍历列表并找到最大的矩形。然后遍历列表并消除包含在最大的所有矩形。这种线性(2x)传递是否会将列表的大小减小到可以通过蛮力方法处理的程度?或者您是否考虑过将列表拆分为子集,并行处理它们,然后对组合结果集进行暴力破解?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-02-10
相关资源
最近更新 更多