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;
            }
        }

如果不满足条件,我当前的算法实际上会返回 -1,但是如果满足条件,它只会返回 0,而不是有效条件的数量。

4

5 回答 5

2

你用

return conditionCount++;

这是不好的做法。有充分的理由。这里发生的是 a)return conditionCount (你设置为零) b)increment conditionCount

b 永远不会在 return 语句之后发生,因此您始终将 0 传递给下一个递归步骤。

您可以使用

return ++conditionCount;

或者更好

conditionCount++;
return conditionCount;
于 2012-12-18T09:34:40.553 回答
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;
}
于 2012-12-18T09:37:00.813 回答
0

你应该return conditionCount;只在函数的末尾。只有return -1;必须在函数的中间。

于 2012-12-18T09:24:51.293 回答
0

return立即停止整个函数并返回一个值。那不是你想要的。您想要累积值并在完成后返回总和。

于 2012-12-18T09:36:25.747 回答
0

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

除此之外,您在递归中要做的就是为每个通过的条件累积 1。

于 2012-12-18T10:18:38.937 回答