随机生成的树结构与他们的父母
问题描述:
我想随机生成看起来像以下对象的树形结构的对象由......组成:随机生成的树结构与他们的父母
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");
我知道如何手动创建对象,以及如何生成随机数字,并且我已经看到了一些随机生成节点以创建分形的东西,但是我突然迷失了方向,因为我从来没有必须以编程方式生成对象。
任何想法,从哪里开始,或使用什么技术将不胜感激。
答
通常情况下,建造这样的物品时,最好有一个设计进出。否则,你会发现自己不得不支持许多应用方法来支持预期的结果。
希望这会有所帮助!
尝试大致如下:)东西
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);
}
}
答
我经常这样做,我可以肯定地帮助一些效率领域。
尝试类似于以下内容的逻辑。在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);
}
}
}
答
最佳的猜测,到目前为止,使用递归函数来处理随机产生孩子&家长:
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错误,直到我将其包装在限制分支总数的计数器中。
真正的问题是:是否有非递归方式来处理它?
那么这将如何改变,如果我想设置在树的大小一些随机参数?比如说我想要一棵随机在2-5层之间的树,每个父亲有0-5个树枝? –
几个选项,根据您的喜好:)。您可以替换数组的List,并在父或子的构造函数中指定一个长度。您可以使用Math.Random()并在整个初始范围内定义随机整数。 或者,使用Math.Random作为第二个参数(限制)写一个For循环,并相应地实例化。 @MattGross –
叫我超级初级开发人员,因为你失去了我在那里:)我得到了Math.random位,不用担心,但在上面的代码示例中,您仍然指定要在主要方法。实际上我现在只是陷入了如何拥有随机深度和随机数的分支,而没有在循环内的循环内写入循环等。 –