在c#(winForms)中创建字符串列表中的树结构

时间:2018-01-16 15:10:26

标签: c# algorithm winforms treeview nodes

我正在努力解决一些逻辑问题,因为我需要从数据库中提取树形结构并添加到TreeView控件。 为了便于解释,我在winforms中创建了一个小例子 我们说我有一些字符串列表

 private List<string> strings;
        public Form1()
        {
            InitializeComponent();
            strings = new List<string>
            {
                "Root1.Parrent1",
                "Root1.Parrent2",
                "Root1.Parrent3.Child1", 
                "Root1.Parrent4.Child2",             
                "Root2.newParrent1.newChild1",
                "Root2.newParrent1.newChild2",
                "Root2.NewParrent2"
            };
        }

所以我想区分每个重复的元素,并制作一个看起来像这样的层次结构,注意我有重复的根和parrents(newparrent1)

 main root {
 root1(                  root2(
    parrent1               newParrent1(
    parrent2                       --newChild1
    parrent3(--child1)             --newChild2)
    parrent4(--child2)     newParrent2)

       }

到目前为止,我的逻辑是卡通,我甚至不知道从哪里开始,我不知道一个节点的菜单子节点如何,完成了一些research,但是没有#39}得到答案。 我只为strings列表的第一项创建了示例,只是为了看看我的逻辑将如何发展。

 string[] splitsArray = strings[0].Split('.');

    TreeNode node = new TreeNode();
    node.Text = splitsArray[0];         
    //creating sub node
    TreeNode subNode = new TreeNode();
    subNode.Text = splitsArray[1];
    //adding
    node.Nodes.Add(subNode);
    treeView1.Nodes[0].Nodes.Add(node);

甚至无法看到我如何将这个逻辑放入循环中。 任何建议都有帮助,甚至是伪代码。谢谢你的时间。

3 个答案:

答案 0 :(得分:2)

由于将其标记为算法问题,我将仅提供算法并将编码部分作为练习。

首先,您创建一个包含所有节点的字典,其中键是节点名称,值是节点对象

nodes

和父表

Root2.newParrent1.newChild1

然后你遍历所有字符串并拆分部分,为每个部分检查(newParrent1, Root2)字典中是否存在名称,如果不存在则将其添加到

并将父项添加到父表。例如

(newChild1, newParrent1)

您会将childParentchildParent添加到Children表格

现在你有一个节点和父节点的字典,我们可以开始创建依赖。

您通过我们刚刚创建的(newParrent1, Root2)表,并将该节点添加到其对应的父级nodes["Root2"].Children.Add(nodes["newParrent1"]);属性

例如,如果您有{{1}}

你将会{{1}}

哦,我们忘记了根节点了吗?

我也会把它作为锻炼。

答案 1 :(得分:1)

public class Program
    {
        public static void Main(string[] args)
        {
            //Your code goes here
            Console.WriteLine("Hello, world!");
            List<string> strings;
            strings = new List<string>()
            {
                "Root1.Parrent1",
                "Root1.Parrent2",
                "Root1.Parrent3.Child1",
                "Root1.Parrent4.Child2",
                "Root2.newParrent1.newChild1",
                "Root2.newParrent1.newChild2",
                "Root2.NewParrent2"
            };
            eat e = new eat(strings);
            Console.WriteLine(e.root.ToJson());
            Console.WriteLine("Press enter to close...");
            Console.ReadLine();
        }
    }
    public class eat
    {
        public node root;
        public eat(List<string> l)
        {
            root = new node("root");
            foreach(string s in l)
            {
                addRow(s);
            }

        }
        public void addRow(string s)
        {
            List<string> l = s.Split('.').ToList<String>();
            node state = root;
            foreach(string ss in l)
            {
                addSoon(state, ss);
                state = getSoon(state, ss);
            }
        }
        private void addSoon(node n, string s)
        {
            bool f = false;
            foreach(node ns in n.soon)
            {
                if (ns.name == s) { f = !f; }
            }
            if (!f) { n.soon.Add(new node(s)); }

        }
        private node getSoon(node n,string s)
        {
            foreach (node ns in n.soon)
            {
                if (ns.name == s) { return ns; }
            }
            return null;
        }
    }
    public class node
    {
        public node(string n)
        {
            name = n;
            soon = new List<node>();
        }
        public string name;
        public List<node> soon;

        public string ToJson()
        {
            String s = "";
            s = s + "{\"name\":\"" + name + "\",\"soon\":[";
            bool f = true;
            foreach(node n in soon)
            {
                if (f) { f = !f; } else { s = s + ","; }
                s = s + n.ToJson();
            }
            s = s + "]}";
            return s;
        }
    }

这是一个不使用词典的解决方案 我们有一个食客,其任务是处理和堆叠类似节点的对象 然后我们有一个节点来处理管理元素和子节点。

他使用tojson类来验证正确的操作

outpot:

{
  "name": "root",
  "soon": [
    {
      "name": "Root1",
      "soon": [
        {
          "name": "Parrent1",
          "soon": [

          ]
        },
        {
          "name": "Parrent2",
          "soon": [

          ]
        },
        {
          "name": "Parrent3",
          "soon": [
            {
              "name": "Child1",
              "soon": [

              ]
            }
          ]
        },
        {
          "name": "Parrent4",
          "soon": [
            {
              "name": "Child2",
              "soon": [

              ]
            }
          ]
        }
      ]
    },
    {
      "name": "Root2",
      "soon": [
        {
          "name": "newParrent1",
          "soon": [
            {
              "name": "newChild1",
              "soon": [

              ]
            },
            {
              "name": "newChild2",
              "soon": [

              ]
            }
          ]
        },
        {
          "name": "NewParrent2",
          "soon": [

          ]
        }
      ]
    }
  ]
}

<强>更新

我刚刚在node类中添加了递归方法,它会返回TreeNode obj,所以我可以放入TreeView,谢谢,这是非常有用的

 public TreeNode GetRoot(List<node> nodes, TreeNode parrent)
        {
            foreach (var node in nodes)                   
              parrent.Nodes.Add(GetRoot(node.children, new TreeNode(node.name)));

            return parrent;
        }

!!!! ---史蒂夫的解决方案更正确,使用词典--- !!!

答案 2 :(得分:1)

如果您正在寻找将这些字符串添加到TreeView的方法,可以使用以下代码。答案是尽量用最少的代码来做:

treeView1.BeginUpdate();
foreach (var s in strings)
{
    TreeNode node = null;
    foreach (var text in s.Split('.'))
    {
        var key = (node == null ? $"{text}" : $"{node.Name}.{text}");
        var nodes = (TreeNodeCollection)((dynamic)node ?? (dynamic)treeView1).Nodes;
        node = (nodes.Find(key, false)).FirstOrDefault() ?? nodes.Add(key, text);
    }
}
treeView1.EndUpdate();

在上面的代码中使用dynamic的原因是因为TreeViewTreeNode都有Nodes集合。您可以使用动态,也可以使用两个不同的代码分支(if(node == null){...}/else{...}),它们非常相似。

仅供您参考的信息TreeNodes集合有一个Find方法,可让您按键查找节点。答案依赖于在添加时为节点设置键,这使我们可以在以后简单地找到它。