递归实验

时间:2012-12-18 09:20:48

标签: c# java .net algorithm recursion

我正在尝试递归以便掌握这个概念。它与语言无关,因此同样的概念适用于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,而不是有效条件的数量。

5 个答案:

答案 0 :(得分:2)

你使用

return conditionCount++;

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

b在return语句之后永远不会发生,所以你总是将0传递给你的下一个递归步骤。

你可以使用

return ++conditionCount;

或更好的

conditionCount++;
return conditionCount;

答案 1 :(得分: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;
}

答案 2 :(得分:0)

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

答案 3 :(得分:0)

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

答案 4 :(得分:0)

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

除此之外,你在递归时所要做的就是为每个传递条件积累1。