2012-12-18 82 views
2

我试图通过递归实验来掌握这个概念。它是语言不可知的,所以相同的概念适用于C#和Java。递归试验

我有一个TreeView它有一些节点。我想遍历每个节点并计算满足一定条件的节点。如果在任何时候条件不满意,我希望算法最终返回-1

每个TreeViewItem只会被视为如果它有Tag名为“条件”(共有3种类型的TreeViewItems - 我只会考虑“条件”的)。

一旦TreeViewItem被发现是“条件”类型,我想检查它是否满足一定的条件。正如我前面提到的,即使只有一个TreeViewItem不满足条件,我希望该算法最终返回-1。

如果算法没有返回-1,我希望它返回它已经找到的有效条件数量 - 也就是说,每次成功传递一个条件时,整数将被递增,最终计数返回到结束。

这是我到目前为止已经试过:

private int CountConditions(TreeViewItem item) 
     { 
      int conditionCount = 0; 

      foreach (TreeViewItem child in item.Items) 
      { 
       int previousCount = CountConditions(child); 

       if (previousCount == -1) 
       { 
        return -1; 
       } 
       else 
       { 
        return conditionCount += previousCount; 
       } 
      } 

      if (item.Tag.Equals("Condition")) 
      { 

       if (/*Condition is not satisfied*/) 
       { 
        return -1; 
       } 
       else 
       { 
        return conditionCount++; 
       } 
      } 
      else 
      { 
       return conditionCount; 
      } 
     } 

我现在的算法确实INFACT返回-1,如果条件不满足,但是如果条件满足,它只是返回0,而不是量的有效条件。

+0

此代码不能同时为“C#”和“Java”。而这当然不是Java。 –

回答

1

这不是一个简单的递归,因为你必须处理错误条件和正常条件。如果没有错误条件,并只需要计算条件的节点数量,你可以写:

private int CountConditions(TreeViewItem item) 
{ 
    int currentCondition = CalculateCondition(item) 
    int childCounts = 0; 
    foreach (TreeViewItem child in item.Items) 
    { 
     int childCount = CountConditions(child); 
     childCounts += childCount; 
    } 
    return currentCondition + conditionCounts 
} 

private int CalculateCondition(TreeViewItem item) 
{ 
    if (item.Tag.Equals("Condition")) 
     return 1; 
    else 
     return 0; 
}   

但是处理错误,你必须有两个检查出现的错误,一个当前节点,以及一个用于子节点,并立即返回,如果遇到条件:

int error = -1 

private int CountConditions(TreeViewItem item) 
{ 
    int currentCondition = CalculateCondition(item) 
    if (currentCondition == error) // new 
     return error;    // new 
    int childCounts = 0; 
    foreach (TreeViewItem child in item.Items) 
    { 
     int childCount = CountConditions(child); 
     if (childCount == error) // new 
      return error;   // new 
     childCounts += childCount; 
    } 
    return currentCondition + conditionCounts 
} 

private int CalculateCondition(TreeViewItem item) 
{ 
    if (item.Tag.Equals("Condition")) 
     if (((item.Header as StackPanel).Children[2] as TextBox).Text.Equals("")) // new 
      return error; // new 
     else    // new 
      return 1; 
    else 
     return 0; 
} 
+0

我会试试这个! –

+0

这似乎已经成功了!非常感谢您的帮助:)您能否解释我做错了什么?因为它毕竟是一个学习练习:) –

+0

@DotNET:在你的代码中,如果一个孩子有conditionCount -1,你设置conditionCount为-1​​,但是你继续检查其他孩子。如果这些剩余子项中的任何一个具有有效的conditionCount,则将其添加到conditionCount中,然后失去-1。如果孩子有-1 conditionCount,那么你应该立即返回。 – Boris

0

你应该return conditionCount;只在结束的功能。只有return -1;必须位于该函数的中间。

+0

自从他学习之后,只提供提示可能会更好。 – phant0m

+0

由于我还在学习,你介意解释为什么?我似乎无法理解这个概念。我会尝试一下你的建议,但如果你能解释为什么我应该这样做,这将非常有帮助:) –

2

您使用

return conditionCount++; 

这是不好的做法。理由很充分。这里所发生的 一)返回conditionCount(你设置为零) 二)增加conditionCount

b从未发生过为return语句之后,让你随时通过0到你的下一个递归步骤。

可以使用

return ++conditionCount; 

或更好

conditionCount++; 
return conditionCount; 
+0

+1是唯一正确的答案。 – phant0m

+0

但是我尝试修改它,但是(虽然它确实返回了正确的计数),但它在返回-1时有时会返回0。 –

+0

看看每个语句。正如它写的那样,如果其中一个孩子有-1计数,它将计数设置为-1。擦除你添加到这个孩子的数量。 – Oren

0

return立刻停止全部功能,并返回一个值。这不是你想要的。您想要累积值并在完成后返回总和。

+0

这就是我最初的想法,但是如果在一个项目不满足条件时他想停止,所以可以放弃。 – phant0m

0

我想你可以通过使用异常简化代码。你所做的是当条件失败时你抛出一个异常,然后你可以捕获另一个递归开始的函数。这将自动展开堆栈并中止计算。捕获异常的函数可以返回任何你想要的。

除此之外,您在递归中所做的所有事情是为每个传递的条件积累1。