C#复杂树-组件数据结构

时间:2018-09-23 10:31:32

标签: c# tree

我正在为一个小问题苦苦挣扎:我需要一个TreeDataScructure。所以我的意思是:我有一个基类,其中包含一个列表(称为RootObject)。并且所有这些RootObjects都有RootObjects子代,这些子代可以自己拥有子代,等等。向所有RootObject中可以添加不同类型的组件。

我这样尝试过:

基类:

RootObject[] Roots;

RootObject class:

RootObject Parent;
RootObject[] Childs;
IGenericComponent[] Components;

问题是:例如,当我需要获取基类中的所有组件时,我会得到一个stackoverflow,因为循环遍历每个Root及其子级需要很长时间。第二个问题是序列化。由于某些组件使用um管理的内存,因此很难对其进行序列化。我的第二种方法是在基类中列出“根和组件”列表,然后仅给出父级和子级的索引,可以从列表中访问。但这很快就变得令人困惑。

有人知道像这样的TreeStructure的好,快速,简便的方法吗?

PS:这是我实现此目的的所有代码:

//These structs are like indexes to the list in the base class
public struct ScoAutoStride : IAutoStride<Sco> 
{
    public int Index { get; internal set; }
    public bool IsValid { get => KerboEngine.Scenery.SceneryObjects.Contains(KerboEngine.Scenery.SceneryObjects[Index]); }

    public Sco Get()
    {
       return KerboEngine.Scenery.SceneryObjects[Index];
    }

    public void Set(Sco newValue)
    {
        KerboEngine.Scenery.SceneryObjects[Index] = newValue;
    }
}

public struct CompAutoStride : IAutoStride<ScoComponent>
{
    public int Index { get; internal set; }
    public bool IsValid { get => KerboEngine.Scenery.SceneryObjectComponents.Contains(KerboEngine.Scenery.SceneryObjectComponents[Index]); }

    public ScoComponent Get()
    {
        return KerboEngine.Scenery.SceneryObjectComponents[Index];
    }

    public ScoComponent<T> CorrectGet<T>() where T : class
    {
        return (ScoComponent<T>)Get();
    }

    public void Set(ScoComponent newValue)
    {
        KerboEngine.Scenery.SceneryObjectComponents[Index] = newValue;
    }
}
//Components:
public abstract class ScoComponent
{
    public Type ChildType { get; internal set; }
    public string Name { get; set; }
    public bool Enabled { get; set; } = true;

    public ScoComponent() { }
}

public class ScoComponent<T> : ScoComponent where T : class
{
    public T RawClass { get; set; }

    protected void InitThis(T value)
    {
        RawClass = value;
        ChildType = value.GetType();
        Name = ChildType.Name;
    }

    public ScoComponent() : base() { }
}
//Root object:
public class Sco
{
    public string Name { get; set; } = "NULL";

    public ScoAutoStride Parent { get; internal set; }

    public List<ScoAutoStride> Childs { get; internal set; }

    public List<CompAutoStride> Components { get; internal set; }

    public object Tag { get; set; }

    public bool Enabled { get; set; } = true;

    public bool Popped { get; set; } = false;

    public const int MaxChilds = int.MaxValue;

    public g_Vec3 Position { get; set; }

    public g_Quatr Rotation { get; set; }

    public g_Vec3 Scale { get; set; }
}

基类:

public class Scenery
{
    public string Name { get; internal set; }
    public List<Sco> SceneryObjects { get; internal set; }
    public List<ScoComponent> SceneryObjectComponents { get; internal set; }
    public int ScoStride { get; private set; } = 0;
    public int CompStride { get; private set; } = 0;

    public Scenery() { }
}

1 个答案:

答案 0 :(得分:0)

如果您仅处理大约10000个项目,那么您的树就不会太深(例如,这种大小的完美平衡的二叉树的深度为14层),因此绝对不应出现堆栈溢出错误,除非:

  1. 您的树实际上是一个列表(例如,完全不平衡,每个节点都有一个孩子,深度为10000级)
  2. 您的树实际上是一个有向循环图(一个对象可以作为其自身的后代出现,因此遍历永远不会终止)
  3. 您的树遍历算法已损坏。

您已经说过(2)不会发生,并且(1)对您来说可能很明显,因此问题似乎出在您尚未与我们共享的树遍历代码中。