2017-10-04 5 views
0

J'essaie de créer une structure arborescente. Chaque classe a un champ parent et une liste d'enfants, c'est la même classe que la classe parente. Trucs de base.C# - Créer une structure arborescente basée sur les valeurs de profondeur et les index de liste

Voici une version de base de la classe que j'utilise. Maintenant, quand j'obtiens les données initiales, j'obtiens toutes ces classes dans une liste. Chaque élément de ma vue arborescente est dans une grande liste, et tout ce que je peux continuer est la valeur de profondeur et l'index de l'élément dans la liste. Donc, la liste ressemblerait fondamentalement quelque chose comme ceci:

(0) -1 
(1) |- 0 
(2)  |-- 1 
(3)  |-- 1 
(4)  | |-- 2 
(5)  |-- 1 

(x) signifie que l'index dans la liste. Le reste des nombres sont les valeurs de profondeur.

Maintenant à mon problème réel. J'ai vraiment du mal à faire ma propre liste basée sur ces valeurs et je n'ai essentiellement obtenu qu'un seul élément dans chaque enfant ajouté et les frères et sœurs sont ignorés. Je ne peux vraiment pas trouver un moyen de les prendre en compte.

Voici mon code jusqu'à présent (ce qui est probablement horriblement mal pour cela):

private List<TreeElement> GenerateTreeStructure(List<TreeElement> baseList) 
{ 
    // Base list is the list I get provided with. 
    List<TreeElement> newList = new List<TreeElement>(); 
    TreeElement root = null; 
    TreeElement previousFolder = null; 
    int previousdepth = -99; 

    for (int i = 0; i < baseList.Count; i++) 
    { 
     TreeElement currentResource = baseList[i]; 
     if (currentResource.depth == -1 && ShowRootFolder) // The root folder. 
     { 
      root = currentResource; 
      // (Name, depth, parent) 
      newList.Add(new TreeElement("Root", currentResource.depth, null)); 
      previousFolder = root; 
      previousdepth = root.depth; 
     } 
     else if (!ShowRootFolder && currentResource.depth <= 0) 
     { 
      // If root folder is not shown, take all the children of the root folder instead. 
      if (currentResource.depth != -1) 
      { 
       previousFolder = new TreeElement(currentResource.name, currentResource.depth, null); 
       previousdepth = previousFolder.depth; 
       newList.Add(previousFolder); 
      } 
     } 
     else 
     { 
      if (currentResource.depth > previousdepth) 
      { 
       TreeElement newResource = new TreeElement(currentResource.name, currentResource.depth, null); 
       previousFolder.children.Add(newResource); 
       previousdepth = currentResource.depth; 
       previousFolder = newResource; 
      } 
     } 
    } 

    return newList; 
} 

J'espère que cela explique mon problème. Je suis coincé avec cela depuis un bon moment et j'espère obtenir de l'aide avec ça!

Merci

Répondre

1

Il est un peu étonnant pourquoi vous renvoyez une liste de TreeElement de cette fonction GenerateTreeStructure? Vous faites une structure d'arbre, n'est-ce pas? Vous devriez retourner juste le rootnode? De toute façon, cela prend une liste avec des valeurs de profondeur et en fait un arbre:

public static TreeElement GenerateTreeStructure(List<TreeElement> baseList) 
{ 
    TreeElement root = null; 
    if (baseList == null || baseList.Count == 0) return root; 

    int baseIdx = -1; 

    TreeElement prevNode = null; 
    TreeElement parent = null; 

    while (baseIdx < baseList.Count - 1) 
    { 
     baseIdx++; 
     TreeElement item = baseList[baseIdx]; 

     if (item.depth == -1) 
     { 
      root = new TreeElement("root", -1, null); 
      prevNode = root; 
      continue; 
     } 

     if (item.depth == prevNode.depth) parent = prevNode.parent; // same level as prevNode 
     else if (item.depth > prevNode.depth) parent = prevNode; // deeper 
     else              // shallower 
     { 
      parent = prevNode.parent; 
      while (parent.depth >= item.depth) parent = parent.parent; 
     } 

     TreeElement newNode = new TreeElement(item.name, item.depth, parent); 
     parent.children.Add(newNode); 
     prevNode = newNode; 
    } 

    return root; 
} 

// to test 
void Traverse(TreeElement branch, int depth) 
{ 
    log(new string('\t', depth) + branch.name); 
    foreach (var subBranch in branch.children) Traverse(subBranch, depth+1); 
} 

Traverse(root, 0); 
+0

Cela a fait exactement ce que je voulais, merci beaucoup! Et pour clarifier pourquoi je l'ai eu retourner une liste: j'ai besoin d'entrer une liste à l'affichage de l'arborescence. Mais je l'ai simplement converti pour retourner une liste en utilisant votre code. – Hertzole

1

J'ai trouvé deux erreurs dans la logique. Voici le code fixe:

// Base list is the list I get provided with. 
     List<TreeElement> newList = new List<TreeElement>(); 
     TreeElement root = null; 
     TreeElement previousFolder = null; 
     int previousdepth = -99; 

     for (int i = 0; i < baseList.Count; i++) 
     { 
      TreeElement currentResource = baseList[i]; 
      if (currentResource.depth == -1 && ShowRootFolder) // The root folder. 
      { 
       root = new TreeElement("Root", currentResource.depth, null); 
       // (Name, depth, parent) 
       newList.Add(root); 
       previousFolder = root; 
       previousdepth = root.depth; 
      } 
      else if (!ShowRootFolder && currentResource.depth <= 0) 
      { 
       // If root folder is not shown, take all the children of the root folder instead. 
       if (currentResource.depth != -1) 
       { 
        previousFolder = new TreeElement(currentResource.name, currentResource.depth, null); 
        previousdepth = previousFolder.depth; 
        newList.Add(previousFolder); 
       } 
      } 
      else 
      { 
       if (currentResource.depth > previousdepth) 
       { 
        TreeElement newResource = new TreeElement(currentResource.name, currentResource.depth, previousFolder); 
        previousFolder.children.Add(newResource); 
        previousdepth = currentResource.depth; 
        previousFolder = newResource; 
       } 
      } 
     } 

     return newList; 

Dans la première « si » vous avez créé une nouvelle racine mais n'a pas l'attribuer à l'objet racine et n'a donc pas l'attribuer à l'objet previousFolder, que vous utilisez dans le dernier « si ». De même, vous n'avez pas passé l'objet previousFolder au constructeur de TreeElement dans la dernière instruction if et cela causerait des problèmes si vous essayiez d'aller à l'élément racine à partir du bas en utilisant le champ parent.

P.S. Le code est très étrange et il semble que vous commencez tout juste à apprendre. Si nous parlons de la structure de l'arbre, je suggère de lire à propos de Composite pattern pour créer un arbre en couple avec Visitor pattern pour le 'visiter'.

+0

Merci pour les corrections. C'était quelque chose que j'ai oublié et raté à réparer après avoir fait quelques tests. Et en ce qui concerne le "code étrange", c'est probablement parce que c'est la première fois que je crée une arborescence dans ces conditions et que je ne fais que tester des choses maintenant. Et pour 'ceci', oui, j'apprends, mais je peux vous assurer que j'ai quelques années d'expérience en C#, et je sais comment créer une vue arborescente ... si je sais ce que sont toutes les classes et ils me sont donnés d'une manière raisonnable. Et pour être honnête, ces liens que vous avez fournis n'ont pas beaucoup aidé, mais je les apprécie toujours! Ce sont des lectures intéressantes! – Hertzole