简体   繁体   English

如何计算任意数量的链接子对象?

[英]How can I count an arbitrary amount of linked child objects?

I apologize if my direct question is unclear, I only know how to explain this through the following example. 如果直接问题不清楚,我深感抱歉,我只知道如何通过以下示例对此进行解释。

I'm trying to calculate the amount of child objects connected to an object. 我正在尝试计算连接到某个对象的子对象的数量。 Each object only holds the children that are connected directly 每个对象仅包含直接连接的子代

I have the following classes: 我有以下课程:

class Question 
{
    public int ID { get; set; } //Primary key
    public string Text { get; set; }
    public string[] Options { get; set; }
    public string Answer { get; set; }


    public List<Link> Links { get; set; }
}

class Link 
{
    public int ID { get; set; }
    public string Answer { get; set; }
    public int QuestionID { get; set; } //Foreign key
}

I use these classes to generate the following dialog editor (see image). 我使用这些类来生成以下对话框编辑器(见图)。

对话框编辑器示例

Example: If I'm at node AB , how can I figure out how many questions are linked underneath it? 示例:如果我在node AB ,如何确定它下面链接了多少个问题? Which in this case is ABA and ABAA ? 在这种情况下, ABAABAA是哪ABAA So the correct answer would be 2. All nodes connected to port Answer B and Answer C should be counted too, should they exist. 因此正确的答案应该是2。如果存在,则也应计算连接到端口Answer BAnswer C所有节点。

I've had little success in coming up with idea's. 我在提出想法方面几乎没有成功。

I use something like the following function to get all direct children of a single question: 我使用类似以下函数的方法来获取单个问题的所有直接子代:

public List<Question> GetDirectChildren(Question question) 
{
    var directChildren = new List<Question>();

    foreach(Link link in question.Links)
        directChildren.Add(myQuestions.FirstOrDefault(f => f.ID == link.QuestionID));

    return directChildren;
}

To get all child-child objects, I would create a nested loop, and another nested loop for each children underneath that. 为了获得所有的子对象,我将创建一个嵌套循环,并在其下为每个子对象创建另一个嵌套循环。 But the problem I can't solve is that there can be an infinite amount of linked objects. 但是我无法解决的问题是可能存在无限数量的链接对象。

Is there a structural way to iterate through or count all linked objects of an object in this scenario? 在这种情况下,是否有结构化的方法可以迭代或计算对象的所有链接对象? With the purpose of retrieving the count of linked objects. 目的是检索链接对象的数量。

You have a tree there which is a very common data structure. 您有一棵树 ,这是一个非常常见的数据结构。 Since in trees, every child of a node is also a tree, you usually use recursion to navigate through the tree. 由于在树中,节点的每个子节点也是一棵树,因此通常使用递归在树中导航。 This is also called tree traversal . 这也称为树遍历

In your case, when you just want to count the nodes in your tree, you just have to break it down to a simpler problem (in general, that's a very common approach when solving difficult problems): 在您的情况下,当您只想对树中的节点进行计数时,只需将其分解为一个更简单的问题即可(通常,在解决难题时这是非常常见的方法):

When you have a tree, which has no children, then the number of nodes is very clearly defined: It's one. 当您有一棵没有子代的树时,节点的数目就非常清楚地定义了:是一个。 Now, when you add one level, how many nodes do you have? 现在,当您添加一个级别时,您有多少个节点? One for the parent, and one for every child. 一个给父母,一个给每个孩子。

Since a child is also a tree, you can now generalize this: For any tree, the number of nodes in the tree is one plus the number of nodes for every child tree. 由于一棵子代也是一棵树,您现在可以将其概括为:对于任何一棵树,该树中的节点数是一个加上每个子树的节点数。

That is your recursive definition, which you can then use to create a recursive function to calculate the total number of nodes in any tree: 这就是您的递归定义,然后您可以使用该定义创建一个递归函数以计算任何树中的节点总数:

public int CountNodes(Node tree)
{
    int count = 1; // current node

    foreach (var child in tree.Children)
    {
        count += CountNodes(child);
    }

    return count;
}

Once you understand this, it's also not a lot more complicated to do different things while traversing the tree. 一旦了解了这一点,遍历树时执行不同的操作也不会变得很复杂。 For example, instead of counting the nodes, you could collect them all in a list; 例如,您可以将它们全部收集在一个列表中,而不必计算节点数。 or eg print a visual representation of your tree. 或例如打印树的视觉表示。

You can recursively call your method GetDirectChildren on all the Link inside your question. 您可以在问题内的所有Link上递归地调用方法GetDirectChildren

public List<Question> GetDirectChildren(Question question) 
{
    var children = new List<Question>();

    if (question.Links.Count > 0)
    {
        foreach(Link link in question.Links)
        {
            Question curQuestion = myQuestions.FirstOrDefault(f => f.ID == link.QuestionID);
            children.Add(curQuestion);
            children.AddRange(GetDirectChildren(curQuestion));
        }
    }
    else
        return children;
}

But if there's at least one cyclical structure, this code will not work. 但是,如果至少有一个循环结构,则此代码将无法工作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM