2017-06-17 148 views
1

我想随机生成看起来像以下对象的树形结构的对象由......组成:随机生成的树结构与他们的父母

Branch parent = new Branch("Start"); 
Branch branch1 = new Branch(parent, "Branch 1"); 
Branch branch2 = new Branch(parent, "Branch 2"); 
Branch branch21 = new Branch(branch2, "Branch 2.1"); 
Branch branch22 = new Branch(branch2, "Branch 2.2"); 

我知道如何手动创建对象,以及如何生成随机数字,并且我已经看到了一些随机生成节点以创建分形的东西,但是我突然迷失了方向,因为我从来没有必须以编程方式生成对象。

任何想法,从哪里开始,或使用什么技术将不胜感激。

回答

1

通常情况下,建造这样的物品时,最好有一个设计进出。否则,你会发现自己不得不支持许多应用方法来支持预期的结果。

希望这会有所帮助!

尝试大致如下:)东西

Branch start = new Branch(); 
CreateChildren(start); 

const int ChildrenLimitCheck = 0; 

private void CreateChildren(Branch parent) { 

    //Use a limit variable so that you can decrease, and if it's equal to a sepcific number(usually 0) exit. 
    int Limit = (int) (Math.random() * 5); 
    //Call the function that's recursive, inside of a function that isn't recursive. This gives you a clean way to interface with the recursive function without excessive lines of code in other areas 
    generateChildren(parent,Limit); 

} 

private void generateChildren(Branch parent,int limit) { 

    //Check to see if we've hit our minimum. If so, exit out of the logic 
    if(limit == ChildrenLimitCheck) 
     return; 

    //Specify the random number of branches created in this instance 
    int numberOfBranches = (int) (Math.random() * 5); 

    for (int i = 0; i < numberOfBranches; i++) { 
     Branch child = new Branch(parent); 
     parent.Children.Add(child); 

     //Depending on what you want to do, either pass i or pass limit. If you don't use limit, you can remove it from this function :) 
     //If you pass i, try doing: 
     //for (int i = numberOfBranches; i > 0; i--) 
     //So that you can eventually get down to 0, to automatically stop your recursive calls with the above return statement. 
     //Seems you just want to run a loop for xxx number of times. This will still grant that, but you won't have to guess the upper limit 
     //of numberOfBranches to exit on, and you'll be able to exit cleanly 
     //This may be what caused your stackoverflow error. For all recursive functions, you need an exit condition or it will run indefinately 
     generateChildren(child,--limit); 
     //generateChildren(child,i); 
    } 
} 
0

我经常这样做,我可以肯定地帮助一些效率领域。

尝试类似于以下内容的逻辑。在Console.Write中放置一个断点以查看深度。这是一个C++面向对象的方法,我个人比LINQ更喜欢性能。我没有对此进行微调,所以LINQ可能会更快。但是,如果您知道自己在做什么,则可以通过自定义方法和继承显着提高性能。

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Threading.Tasks; 

namespace ConsoleApplication11 
{ 
    public class Branch 
    { 
     //Branch Name 
     public string BranchName { get; set; } 
     //Add depth 
     public List<Branch> Children = new List<Branch>(); 
     //Add a parent 
     public Branch Parent = null; 
     public Branch() 
     { 

     } 
     public Branch(string BranchName) 
     { 
      this.BranchName = BranchName; 
     } 
     public Branch(Branch Parent, string BranchName) 
     { 
      this.Parent = Parent; 
      this.BranchName = BranchName; 
     } 

     //Internal Functions 
     public bool HasParent() 
     { 
      return this.Parent != null; 
     } 

     public Branch getParent() 
     { 
      return this.Parent; 
     } 
    } 
    //Wrap a list inside of a class so we can have leverage over the add, and create our own functions for our need 
    public class BranchList 
    { 
     public List<Branch> branchParentList = new List<Branch>(); 

     public void AddBranchToParent(Branch parent, Branch child) 
     { 

      foreach (Branch node in branchParentList) 
      { 
       if (node == parent) 
       { 
        node.Children.Add(child); 
       } 
      } 
     } 

     public void AddBranchAsChild(string parent, Branch child) 
     { 

      foreach (Branch node in branchParentList) 
      { 
       if (node.BranchName == parent) 
       { 
        node.Children.Add(child); 
        return;//Exit out, don't do the other loop. We found it 
       } 
       //Depth 
       AddBranchAsChildInChildren(node, child,parent); 
      } 
     } 
     public void AddBranchAsChildInChildren(Branch branch,Branch Child,string parent) 
     { 
      foreach(Branch child in branch.Children) 
      { 
       if (child.BranchName == parent) 
        child.Children.Add(Child); 
      } 
     } 
     public void AddBranchAsChildInChildren(Branch branch, string Child, string parent) 
     { 
      foreach (Branch child in branch.Children) 
      { 
       if (child.BranchName == parent) 
        child.Children.Add(new Branch() { BranchName=Child }); 
      } 
     } 
     public void AddBranchAsChild(string parent, string child) 
     { 

      foreach (Branch node in branchParentList) 
      { 
       if (node.BranchName == parent) 
       { 
        node.Children.Add(new Branch() { BranchName = child }); 
        return; 
       } 
       //Depth 
       AddBranchAsChildInChildren(node, child, parent); 
      } 

     } 
     public void AddBranchAsParent(Branch Branch, Branch Child) 
     { 
      if (branchParentList.Contains(Branch) == false) 
       throw new Exception("Parent exists"); 

      foreach (Branch b in branchParentList) 
      { 
       if (b == Child) 
       { 
        b.Parent = Branch; 
       } 
      } 
     } 
     public void AddParent(Branch Parent) 
     { 
      if (branchParentList.Contains(Parent)) 
       throw new Exception("Parent exists"); 
      this.branchParentList.Add(Parent); 
     } 
    } 
    //Wrap the list, use it as an interface 
    public class BranchManager 
    { 
     public BranchList branchList = new BranchList(); 

     public BranchManager() 
     { 

     } 
     public void AddParent(Branch Branch) 
     { 
      branchList.AddParent(Branch); 
     } 
     public void AddBranchAsChild(Branch Parent, Branch Child) 
     { 
      branchList.AddBranchToParent(Parent, Child); 
     } 
     public void AddBranchAsChild(string ParentName, Branch Child) 
     { 
      branchList.AddBranchAsChild(ParentName, Child); 
     } 
     public void AddBranchAsChild(string ParentName, string ChildName) 
     { 
      branchList.AddBranchAsChild(ParentName, ChildName); 
     } 
    } 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      /* 
       Branch parent = new Branch("Start"); 
       Branch branch1 = new Branch(parent, "Branch 1"); 
       Branch branch2 = new Branch(parent, "Branch 2"); 
       Branch branch21 = new Branch(branch2, "Branch 2.1"); 
       Branch branch22 = new Branch(branch2, "Branch 2.2"); 
      */ 
      BranchManager branchManager = new BranchManager(); 

      branchManager.AddParent(new Branch("Start")); 

      branchManager.AddBranchAsChild("Start", "Branch 1"); 
      branchManager.AddBranchAsChild("Start", "Branch 2"); 
      branchManager.AddBranchAsChild("Branch 2", "Branch 2.1"); 
      branchManager.AddBranchAsChild("Branch 2", "Branch 2.2"); 

      Console.WriteLine(branchManager.branchList.branchParentList.Count); 

     } 
    } 
} 
+0

那么这将如何改变,如果我想设置在树的大小一些随机参数?比如说我想要一棵随机在2-5层之间的树,每个父亲有0-5个树枝? –

+0

几个选项,根据您的喜好:)。您可以替换数组的List,并在父或子的构造函数中指定一个长度。您可以使用Math.Random()并在整个初始范围内定义随机整数。 或者,使用Math.Random作为第二个参数(限制)写一个For循环,并相应地实例化。 @MattGross –

+0

叫我超级初级开发人员,因为你失去了我在那里:)我得到了Math.random位,不用担心,但在上面的代码示例中,您仍然指定要在主要方法。实际上我现在只是陷入了如何拥有随机深度和随机数的分支,而没有在循环内的循环内写入循环等。 –

0

最佳的猜测,到目前为止,使用递归函数来处理随机产生孩子&家长:

Branch start = new Branch(); 
generateChildren(start); 

private void generateChildren(Branch parent) { 

    int numberOfBranches = (int) (Math.random() * 5); 

    for (int i = 0; i < numberOfBranches; i++) { 
     Branch child = new Branch(parent); 
     generateChildren(child); 
    } 
} 

它正确创建分公司的对象链接与父母的列表。我遇到了一个StackOverflow错误,直到我将其包装在限制分支总数的计数器中。

真正的问题是:是否有非递归方式来处理它?