2009-02-03 8 views
2

J'ai un grand ensemble de résultats assemblé dans une relation parent/enfant. J'ai besoin de marcher dans l'arbre et afficher les résultats à l'utilisateur.C# Itération de grand arbre

Je l'ai fait avant d'utiliser la récursivité, mais parce que mon jeu de résultats peut être grand, je veux éviter la possibilité de recevoir une exception StackOverflowException.

J'ai trouvé le suivant example sur MSDN qui utilise une pile. Le problème que j'ai est parce qu'une pile est le dernier entré, le premier, mes données n'apparaissent pas correctement. Je voudrais que ça ressemble à ce qui suit:


LeveL 1 
Level 1.1 
Level 1.1.1 
Level 1.1.2 
Level 1.2 
Level 1.2.1 
Level 1.2.2 

Mais il ressemble à:


LeveL 1 
Level 1.2 
Level 1.2.2 
Level 1.2.1 
Level 1.1 
Level 1.1.2 
Level 1.1.1 

Toutes les idées?

Voici un exemple de mon code. En supposant que le DataTable dt a les colonnes suivantes: ID, ParentID et texte

private struct Item 
    { 
     public string Text; 
     public int ID; 
     public int ParentID; 
    } 

    private void BuildView() 
    { 
     Stack<Item> itemTree = new Stack<Item>(40); 

     //Get All Parent Nodes 
     DataView dv = new DataView(dt); 
     dv.RowFilter = "ParentID = 0"; 

     //Add the parent nodes to the stack 
     foreach (DataRowView drv in dv) 
     { 
      Item item = new Item(); 
      item.Text = drv["Text"].ToString(); 
      item.ID = drv["ID"].ToString(); 
      item.ParentID = drv["ParentID"].ToString(); 
      itemTree.Push(item); 
     } 

     //Go through the stack one node at a time 
     while (itemTree.Count > 0) 
     { 
      Item currentItem = itemTree.Pop(); 
      Debug.WriteLine(currentItem.Text); 

      //Get children of current node 
      dv.RowFilter = String.Format("ParentID = {0}", currentItem.ID); 
      if (dv.Count > 0) 
      { 
       //Add child nodes to the stack 
       foreach (DataRowView drvChild in dv) 
       { 
        Item item = new Item(); 
        item.Text = drvChild["Text"].ToString(); 
        item.ID = drvChild["ID"].ToString(); 
        item.ParentID = drvChild["ParentID"].ToString(); 
        itemTree.Push(item); 
       } 
      } 
     } 

    } 

Répondre

1

Poussez vos articles sur la pile dans l'ordre inverse, soit 2 avant 1.

Exemple:

// suppose I want to push children[] onto the stack 

for (int i = children.Length - 1; i >= 0; i--) 
{ 
    stack.Push(children[i]); 
} 

Pour ce faire, dans votre code, essayez la déclaration for-each suivante:

foreach (DataRowView drvChild in dv.Reverse()) 
+0

Je ne sais pas si ça marchera de cette façon. Peux-tu expliquer? – Niyaz

+0

@Niyaz: Mise à jour de ma réponse avec un exemple. –

+0

Oui. Mais pouvez-vous expliquer comment cela donnera la réponse requise? Je ne peux pas comprendre. – Niyaz

3

Dans l'algorithme actuel, vous allez à l'enfant dès la première.

Faites-le gauche enfant en premier. C'est tout.

Par exemple, dans votre code il peut y avoir quelque chose comme:

node = node.rightChild() 

Modifier à

node = node.leftChild() 

Ceci est la solution générale pour ce genre de questions.

Étant donné que l'implémentation MSDN n'expose pas ce type de code, je ne peux pas commenter cela.

+0

Je pense qu'il ya une faute de frappe là ... les deux lignes de code sont identiques. –

+0

Comment est-ce que je ferais ceci, en utilisant mon exemple de code ci-dessus? – user62064

0

Si c'est simplement la commande qui vous préoccupe, passez de l'utilisation d'une pile à l'utilisation d'une file d'attente. Ils sont identiques pour des raisons pratiques, à la différence qu'une file d'attente est la première en premier.

+0

L'utilisation d'une file d'attente la transforme en traversée en largeur, au lieu de la traversée en profondeur souhaitée. –

+0

Zach, Pas nécessairement. Il devient la largeur d'abord seulement si vous faites la largeur en premier. Mais généralement, nous utilisons la file d'attente dans les premières recherches de largeur. – Niyaz

+0

Si j'utilise une file d'attente, les données apparaissent comme ceci. Niveau 1 Niveau 1.1 Niveau 1.2 Niveau 1.1.1 Niveau 1.1.2 Niveau 1.2.1 Niveau 1.2.2 – user62064

0

En changeant mon itération des nœuds enfants dans l'ordre inverse, ils affichent comme vous le souhaitez

//Add child nodes to the stack 
for (int i = dv.Count - 1; i >= 0; i--) 
{ 
    DataRowView drvChild = dv[i]; 
    Item item = new Item(); 
    item.Text = drvChild["Text"].ToString(); 
    item.ID = drvChild["ID"].ToString(); 
    item.ParentID = drvChild["ParentID"].ToString(); 
    itemTree.Push(item); 
} 
+0

Typo? L'index i ne semble pas être utilisé. –

+0

Oups - réparé maintenant. – user62064