【问题标题】:Why I am getting two different results for the same design?为什么我会为同一个设计得到两个不同的结果?
【发布时间】:2016-07-27 20:36:41
【问题描述】:

快速提问:

我有一堆(云)坐标,我倾向于找到整个坐标的四个角坐标。我的意思是:

MyDesiredResult = { SmallestX, BiggestY, BiggestX, SmallestY }

我使用这个旧例程来获得我的价值观,它是正确的一个

double smallestX = MyCloud[0].X;       // assing X of first element to my result controller
var tempCoordPoint = MyCloud[0];       // assign first element to my result controller

for (int i = 0; i < MyCloud.Count; i++)
{
    if (smallestX > MyCloud[i].X)      // find minimum X
    {
        smallestX = MyCloud[i].X;
        tempCoordPoint = MyCloud[i];
    }
}

MyResult.Add(tempCoordPoint);           // add to my list

但是,我需要这样做 四次(对于四次结果)。因此,我试图通过将其更改为仅使用一次的 New Routine 来优化我的代码:

List<CoordPoint> MySortedList = MyCloud.Select(c => new CoordPoint { X = c.X, Y = c.Y, Z = c.Z, Color = c.Color }).ToList();

MySortedList.Sort((c1, c2) => c1.X.CompareTo(c2.X));     // sort on X
var temp = MySortedList[MySortedList.Count - 1];         // hold biggest X in a temp variable
MyResult.Add(MySortedList[0]);                           // add smallest X to my result

MySortedList.Sort((c1, c2) => c1.Y.CompareTo(c2.Y)); ;   // sort on Y
MyResult.Add(MySortedList[MySortedList.Count - 1]);      // add biggest Y to my result 
MyResult.Add(temp);                                      // add biggest X to my result
MyResult.Add(MySortedList[0]);                           // add smallest Y to my result

但它给出了不同的结果。我想显示一个示例输入、当前输出和所需的输出。我可以跳过样本输入(巨大的负载)并显示结果。谁能指出我做错了什么?

对于相同的输入:

旧例程的结果

(0, 4), (15, 12), (23, 6), (19, 0)

新例程的结果

(0, 4), (18, 12), (23, 6), (18, 0)

【问题讨论】:

  • 你说两个不同的代码 sn-ps 产生不同的结果,但没有说明正确的结果是什么。
  • @Servy 我做到了。请参阅结果部分之前的“P.S 旧例程是正确的!”。新套路不应该导致不同的结果!这就是问题所在。
  • 你的问题的基本前提不应该是在后文中。
  • @Servy 感谢您的指出。我将编辑我的帖子。但你知道,我认为我有更好的讨论。我刚刚注意到这两个结果都是有效的。因为两者都是{ SmallestX, BiggestY, BiggestX, SmallestY } 的形式。但是,如何使用更简单的新例程找到正确的角点来解决我的问题呢?嗯..

标签: c# algorithm sorting design-patterns logic


【解决方案1】:

我会用另一个问题来回答你的问题:

如果两个点具有相同的 Y 坐标并且 Y 坐标恰好是最小值或最大值,会发生什么情况? X坐标也一样?

让我用一个例子来说明。假设你有这 4 点:

(0, 0), (1, 0), (0, 1), (1, 1)

您的原始算法将返回:

(0, 0), (0, 1), (1, 0), (0, 0)

现在假设我们将原来的 4 个点洗牌:

(1, 1), (0, 1), (1, 0), (0, 0)

如果你在上面运行你的原始算法,你会得到这个:

(0, 1), (1, 1), (1, 1), (1, 0)

根据您的说法,原始算法是正确的,但我只是以两个不同的顺序给了它相同的一组点并得到了两个不同的答案。那么哪个答案是正确的呢?实际的预期结果是什么?

现在,我没有提供您的新算法的结果是有原因的,那是因为我不知道您的新算法会产生什么结果。我不知道的原因是List&lt;T&gt;.Sort 执行不稳定的排序。这意味着比较“相等”的两个元素不一定按顺序排列。因此,如果我们的输入是(0, 0), (1, 0), (0, 1), (1, 1),则在尝试按 X 坐标排序后,以下所有可能都是有效的:

(0, 0), (0, 1), (1, 0), (1, 1)

(0, 1), (0, 0), (1, 0), (1, 1)

(0, 1), (0, 0), (1, 1), (1, 0)

(0, 0), (0, 1), (1, 1), (1, 0)

List&lt;T&gt;.Sort 可以产生其中任何一种。如果您有更多重复的 X 坐标,您将有更多可能的排序。这被称为不稳定的原因是因为两个相等元素(例如(0, 0)(0, 1))的相对顺序在排序后没有保留。排序算法可能会交换它们的位置。

【讨论】:

  • 在我继续阅读之前我就知道你会问什么:D 我只是在想它。你是对的..好抓! +1,谢谢。不过,请允许我一些时间来回答其他问题,我想我需要在Ys 相等的情况下采用最大的X,如果Xs 相等,则采用最大的Y,依此类推。正在努力
  • @FirstStep 这取决于你实际上想用这些点做什么。如果您只是想获取边界框的角点,那么您需要创建新点,因为一组点不一定包含边界框角点处的点。考虑(-1, 0), (0, 1), (1, 0), (0, -1);角是(-1, -1), (-1, 1), (1, 1), (1, -1),没有一个在输入集中。
  • 好吧,我可能不同意你的观点。我只是想得到轮廓。并获得边界坐标将允许我创建我的轮廓。等高线的坐标是(XFromSmallestXCoord, YFromHighestYCoord), (XfromHighestXCoord, YFromHighestYCoord), (XFromHighestXCoord, YFromHighestXCoord ), (XFromSmallestXCoord, YFromSmallestYCoordinate),但接下来我们直接解决问题。例如,如果我们有几个SmallestXCoordinate 等等。而且我认为它不再重要了。
  • @FirstStep 听起来您实际上想要的是convex hull,您的算法仍然无法正确执行。幸运的是,有许多已公开的用于计算凸包的算法。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-10-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-04-06
  • 2021-04-02
相关资源
最近更新 更多