2012-12-18 28 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。