Data structures 为什么根据初始深度生成树是无限循环(递归)?

Data structures 为什么根据初始深度生成树是无限循环(递归)?,data-structures,tree,computer-science,Data Structures,Tree,Computer Science,有人帮我找到无限循环(递归)的原因吗 root=生成树(0)//仅根(0初始深度) root=generate_tree(1)//根和两个子树(1个初始深度) 0或1初始_深度正常工作,但如果大于1,则将正常工作 造成无限循环 下面是我根据初始深度创建树的伪代码 class Node children = [] generate_subtree() //let assume it will create two random nodes and pass it t

有人帮我找到无限循环(递归)的原因吗

root=生成树(0)//仅根(0初始深度)

root=generate_tree(1)//根和两个子树(1个初始深度)

0或1初始_深度正常工作,但如果大于1,则将正常工作 造成无限循环

下面是我根据初始深度创建树的伪代码

class Node
    children = []
    generate_subtree()
        //let assume it will create two random nodes and pass it to children
        children = two random nodes


Node generate_tree(initial_depth)
if initial_depth == 0
   return a random Node
else
   root = random node
   grow_tree(root, initial_depth)
   return root;


grow_tree(tree, init_depth)
    if initial_depth == 1
        tree.generate_subtree()
    else if initial_depth > 1
        tree.generate_subtree()
        for subtree in tree.children
            grow_tree(subtree, initial_depth - 1)
更新 我包括了我的实际代码

我正在用C#script开发Unity

GNode.cs

using System;
using System.Collections.Generic;

namespace GP
{
    public abstract class GNode
    {
        public const float TERMINAL_RATIO = 0.2f; 

        public String data { get; private set; }
        public bool is_terminal { get; private set; }
        public int depth { get; private set; }
        public GNode[] children { get; private set; }

        public abstract void initialize(int depth = 0);
        public abstract void generate_subtree(List<GNode> nodes, List<GNode> terminals);

        public GNode() { }

        public GNode(String data, bool is_terminal, int depth = 0)
        {
            this.initialize(data, is_terminal, depth);
        }

        protected void initialize(String data, bool is_terminal, int depth = 0)
        {
            this.data = data;
            this.is_terminal = is_terminal;
            this.depth = depth;
            this.children = new GNode[0];
        }

        protected void generate_subtree(List<GNode> nodes, List<GNode> terminals, int num_of_childrens)
        {
            List<GNode> classes = new List<GNode>();
            for (int i = 0; i < num_of_childrens; i++)
            {
                if (nodes.Count > 0 && Utility.GetRandomFloat() > GNode.TERMINAL_RATIO)
                    classes.Add(nodes[Utility.GetRandomNumber(0, nodes.Count)]);
                else
                    classes.Add(terminals[Utility.GetRandomNumber(0, terminals.Count)]);
                    classes[i].initialize(this.depth + 1);
            }
            this.children = classes.ToArray();
        }
    }

    #region NODES
    public class ConstantNum : GNode
    {
        public ConstantNum(int depth = 0)
        {
            this.initialize(depth);
        }

        public override void initialize(int depth = 0)
        {
            base.initialize(Utility.GetRandomNumber(0, 9).ToString(), true, depth);
        }

        public override void generate_subtree(List<GNode> nodes, List<GNode> terminals)
        {
            base.generate_subtree(nodes, terminals, 2);
        }
    }

    public class RandomNum : GNode
    {
        public RandomNum(int depth = 0)
        {
            this.initialize(depth);
        }

        public override void initialize(int depth = 0)
        {
            base.initialize("random", true, depth);
        }

        public override void generate_subtree(List<GNode> nodes, List<GNode> terminals)
        {
            base.generate_subtree(nodes, terminals, 2);
        }
    }
    #endregion


    #region TERMINALS
    public class MeasureNode : GNode
    {
        public String Measure { set; private get; }

        public override void initialize(int depth = 0)
        {
            base.initialize(this.Measure, true, depth);
        }

        public override void generate_subtree(List<GNode> nodes, List<GNode> terminals)
        {
             base.generate_subtree(nodes, terminals, 2);
        }
    }

    public class CanMove_UP : MeasureNode
    {
        public override void initialize(int depth = 0)
        {
            base.Measure = "CanMove_UP";
            base.initialize(depth);
        }
    }

    public class CanMove_DOWN : MeasureNode
    {
        public override void initialize(int depth = 0)
        {
            base.Measure = "CanMove_DOWN";
            base.initialize(depth);
        }
    }

    public class CanMove_LEFT : MeasureNode
    {
        public override void initialize(int depth = 0)
        {
            base.Measure = "CanMove_LEFT";
            base.initialize(depth);
        }
    }

    public class CanMove_RIGHT : MeasureNode
    {
        public override void initialize(int depth = 0)
        {
            base.Measure = "CanMove_RIGHT";
            base.initialize(depth);
        }
    }
    #endregion
}
using System;
using System.Collections.Generic;

namespace GP
{
    public class Tree
    {
        private int initial_depth;
        private List<GNode> nodes;
        private List<GNode> terminals;
        private GNode root;

        public Tree(int initial_depth, List<GNode> nodes, List<GNode> terminals, GNode root = null)
        {
            this.initial_depth = initial_depth;
            this.nodes = nodes;
            this.terminals = terminals;
            this.root = root;
            if (root == null)
                this.root = this.generate_tree(initial_depth, nodes, terminals);
        }

        public GNode generate_tree(int initial_depth, List<GNode> nodes, List<GNode> terminals)
        {
            if (initial_depth == 0)
                return terminals[Utility.GetRandomNumber(0, terminals.Count)]; //construct a random node from terminals
            else
            {
                GNode tree;
                if (Utility.GetRandomFloat() <= GNode.TERMINAL_RATIO)
                    tree = terminals[Utility.GetRandomNumber(0, terminals.Count)];
                else
                    tree = nodes[Utility.GetRandomNumber(0, nodes.Count)];
                this.grow_tree(tree, initial_depth, nodes, terminals);
                return tree;
            }
        }

        public void grow_tree(GNode tree, int init_depth, List<GNode> nodes, List<GNode> terminals)
        {
            if (initial_depth == 1)
                tree.generate_subtree(new List<GNode>(), terminals); //empty nodes
            else if (initial_depth > 1)
            {
                tree.generate_subtree(nodes, terminals);
                foreach (GNode subtree in tree.children)
                    this.grow_tree(subtree, initial_depth - 1, nodes, terminals);
            }
        }
    }
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public static class Utility
{
    private static readonly System.Random getRandom = new System.Random();

    public static int GetRandomNumber(int min, int max)
    {
        lock (getRandom)
        {
            return getRandom.Next(min, max);
        }
    }

    public static int GetRandomNumber(int max)
    {
        return GetRandomNumber(0, max);
    }

    public static float GetRandomFloat(float min = 0.0f, float max = 1.0f)
    {
        return Random.Range(min, max);
    }
}
我已经翻译了您所编写的伪代码,它工作正常。
你可以发布你的代码吗,或者你可以从我的代码中验证你缺少了什么。

哈曼你好,我在我的帖子中包含了代码,你能看一下吗you@IvanArnie好的,这比我预期的要长,我需要一些时间来弄清楚这件事。
using System;
using System.Collections.Generic;

namespace GP
{
    public class Tree
    {
        private int initial_depth;
        private List<GNode> nodes;
        private List<GNode> terminals;
        private GNode root;

        public Tree(int initial_depth, List<GNode> nodes, List<GNode> terminals, GNode root = null)
        {
            this.initial_depth = initial_depth;
            this.nodes = nodes;
            this.terminals = terminals;
            this.root = root;
            if (root == null)
                this.root = this.generate_tree(initial_depth, nodes, terminals);
        }

        public GNode generate_tree(int initial_depth, List<GNode> nodes, List<GNode> terminals)
        {
            if (initial_depth == 0)
                return terminals[Utility.GetRandomNumber(0, terminals.Count)]; //construct a random node from terminals
            else
            {
                GNode tree;
                if (Utility.GetRandomFloat() <= GNode.TERMINAL_RATIO)
                    tree = terminals[Utility.GetRandomNumber(0, terminals.Count)];
                else
                    tree = nodes[Utility.GetRandomNumber(0, nodes.Count)];
                this.grow_tree(tree, initial_depth, nodes, terminals);
                return tree;
            }
        }

        public void grow_tree(GNode tree, int init_depth, List<GNode> nodes, List<GNode> terminals)
        {
            if (initial_depth == 1)
                tree.generate_subtree(new List<GNode>(), terminals); //empty nodes
            else if (initial_depth > 1)
            {
                tree.generate_subtree(nodes, terminals);
                foreach (GNode subtree in tree.children)
                    this.grow_tree(subtree, initial_depth - 1, nodes, terminals);
            }
        }
    }
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public static class Utility
{
    private static readonly System.Random getRandom = new System.Random();

    public static int GetRandomNumber(int min, int max)
    {
        lock (getRandom)
        {
            return getRandom.Next(min, max);
        }
    }

    public static int GetRandomNumber(int max)
    {
        return GetRandomNumber(0, max);
    }

    public static float GetRandomFloat(float min = 0.0f, float max = 1.0f)
    {
        return Random.Range(min, max);
    }
}
class Node:

    def __init__(self):
        self.children = []

    def generate_subtree(self):
        self.children.append(Node())
        self.children.append(Node())


def generate_tree(initial_depth):
    if initial_depth == 0:
        return Node()
    else:
        root = Node()
        grow_tree(root, initial_depth)
        return root


def grow_tree(tree, initial_depth):
    if initial_depth == 1:
        tree.generate_subtree()
    elif initial_depth > 1:
        tree.generate_subtree()
        for subtree in tree.children:
            grow_tree(subtree, initial_depth - 1)

tree = generate_tree(4)