Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/290.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/qt/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在C#中定义一个可继承的树类,以构建由不同类类型组成的树状数据结构?_C# - Fatal编程技术网

如何在C#中定义一个可继承的树类,以构建由不同类类型组成的树状数据结构?

如何在C#中定义一个可继承的树类,以构建由不同类类型组成的树状数据结构?,c#,C#,我已经围绕这个主题阅读了一段时间,但我对C#语法的了解还不够透彻。希望这对你来说是清楚的,你愿意帮助我。我发现的示例是相同类型或类的树结构,这不是我在这里需要的 简言之,我希望能够定义一个任意类,如下面的NodeClassA、NodeClassB、NodeClassC,并能够将任意数量的这些类相互附加,以形成树数据结构,如下面任意所示 每个节点都应该能够访问其父节点 有人能帮助正确定义下面的MyTreeClass吗 NodeClassB __NodeClassC __诺德克拉萨 ____Node

我已经围绕这个主题阅读了一段时间,但我对C#语法的了解还不够透彻。希望这对你来说是清楚的,你愿意帮助我。我发现的示例是相同类型或类的树结构,这不是我在这里需要的

简言之,我希望能够定义一个任意类,如下面的NodeClassA、NodeClassB、NodeClassC,并能够将任意数量的这些类相互附加,以形成树数据结构,如下面任意所示

每个节点都应该能够访问其父节点

有人能帮助正确定义下面的MyTreeClass吗

NodeClassB
__NodeClassC
__诺德克拉萨
____NodeClassB
____NodeClassB
____诺德克拉萨
__诺德克拉萨
____NodeClassC
__NodeClassB
__NodeClassC

class MyTreeClass
{
    public void AddChild(T NodeClassX) { }
    public T GetChild() { }
}
class NodeClassA:MyTreeClass
{
    public void foo(int a) { }
}

class NodeClassB : MyTreeClass
{
    public void foo(int b) { }
}

class NodeClassC : MyTreeClass
{
    public void foo(int c) { }
}

您可能正在寻找,这是建模树结构的常用方法,例如,文件系统中有叶子(文件)和容器(文件夹),容器可以包含其他容器或叶子本身

在您的例子中,至少按照您目前描述的方式,它更简单一些,因为这些节点之间没有行为差异。因此,对于您的结构,节点实际上可以是浅层的,您只需要在基类中实现组合。这样,你就没有叶子,只有(不同的)容器

public abstract class BaseNode
{
    public IList<BaseNode> Children
    { get; } = new List<BaseNode>();
}

public class NodeClassA : BaseNode { }
public class NodeClassB : BaseNode { }
public class NodeClassC : BaseNode { }
公共抽象类BaseNode
{
公营儿童
{get;}=新列表();
}
公共类NodeClassA:BaseNode{}
公共类NodeClassB:BaseNode{}
公共类NodeClassC:BaseNode{}

然后您就可以构建结构了。

您可能正在寻找树结构建模的常用方法,例如,文件系统中有一个叶子(文件)和容器(文件夹),容器可以包含其他容器或叶子本身

在您的例子中,至少按照您目前描述的方式,它更简单一些,因为这些节点之间没有行为差异。因此,对于您的结构,节点实际上可以是浅层的,您只需要在基类中实现组合。这样,你就没有叶子,只有(不同的)容器

public abstract class BaseNode
{
    public IList<BaseNode> Children
    { get; } = new List<BaseNode>();
}

public class NodeClassA : BaseNode { }
public class NodeClassB : BaseNode { }
public class NodeClassC : BaseNode { }
公共抽象类BaseNode
{
公营儿童
{get;}=新列表();
}
公共类NodeClassA:BaseNode{}
公共类NodeClassB:BaseNode{}
公共类NodeClassC:BaseNode{}

然后您就可以构建您的结构了。

这在严格的类型安全方式下是不可能的,因为类型安全是在编译时确保的,这需要静态声明类型。但树是在运行时使用不同的节点类型动态构建的

方法是使用一个可以是泛型的静态节点数据类型。可以从给定的基本数据类型派生不同类型的数据。使用“变形”来处理它们。也就是说,在不同的实现中使用相同的方法集

public class TreeNode<T>
{
    public T Data { get; set; }

    private List<TreeNode<T>> _children = new List<TreeNode<T>>();
    public IEnumerable<TreeNode<T>> Children => _children;

    public TreeNode<T> AddChild(T data)
    {
        var node = new TreeNode<T> { Data = data };
        _children.Add(node);
        return node;
    }

    public void VisitPreOrder(Action<T, int> action, int level)
    {
        action(Data, level);
        foreach (TreeNode<T> node in Children) {
            node.VisitPreOrder(action, level + 1);
        }
    }
}

public class Tree<T>
{
    public TreeNode<T> Root { get; } = new TreeNode<T>();

    public void VisitPreOrder(Action<T, int> action)
    {
        Root.VisitPreOrder(action, 0);
    }
}
根据示例创建树结构

TreeNode<A> node;

var tree = new Tree<A>();
tree.Root.Data = new B { Index = 0 };            // NodeClassB
tree.Root.AddChild(new C { Index = 1 });         // __NodeClassC
node = tree.Root.AddChild(new A { Index = 2 });  // __NodeClassA
node.AddChild(new B { Index = 3 });              // ____NodeClassB
node.AddChild(new B { Index = 4 });              // ____NodeClassB
node.AddChild(new A { Index = 5 });              // ____NodeClassA
node = tree.Root.AddChild(new A { Index = 6 });  // __NodeClassA
node.AddChild(new C { Index = 7 });              // ____NodeClassC
tree.Root.AddChild(new B { Index = 8 });         // __NodeClassB
tree.Root.AddChild(new C { Index = 9 });         // __NodeClassC 
b0
____C1
____A 2
________b3
________B 4
________A 5
____A 6
________C7
____b8
____C 9

注意,在声明
树节点
类时,您不需要知道
t
的具体数据类型,因为
t
是泛型的。你不妨申报一下

var stringTree = new Tree<string>();
var intTree = new Tree<int>();
var stringTree=newtree();
var intTree=新树();

这在严格的类型安全方式下是不可能的,因为类型安全是在编译时确保的,这需要静态声明类型。但树是在运行时使用不同的节点类型动态构建的

方法是使用一个可以是泛型的静态节点数据类型。可以从给定的基本数据类型派生不同类型的数据。使用“变形”来处理它们。也就是说,在不同的实现中使用相同的方法集

public class TreeNode<T>
{
    public T Data { get; set; }

    private List<TreeNode<T>> _children = new List<TreeNode<T>>();
    public IEnumerable<TreeNode<T>> Children => _children;

    public TreeNode<T> AddChild(T data)
    {
        var node = new TreeNode<T> { Data = data };
        _children.Add(node);
        return node;
    }

    public void VisitPreOrder(Action<T, int> action, int level)
    {
        action(Data, level);
        foreach (TreeNode<T> node in Children) {
            node.VisitPreOrder(action, level + 1);
        }
    }
}

public class Tree<T>
{
    public TreeNode<T> Root { get; } = new TreeNode<T>();

    public void VisitPreOrder(Action<T, int> action)
    {
        Root.VisitPreOrder(action, 0);
    }
}
根据示例创建树结构

TreeNode<A> node;

var tree = new Tree<A>();
tree.Root.Data = new B { Index = 0 };            // NodeClassB
tree.Root.AddChild(new C { Index = 1 });         // __NodeClassC
node = tree.Root.AddChild(new A { Index = 2 });  // __NodeClassA
node.AddChild(new B { Index = 3 });              // ____NodeClassB
node.AddChild(new B { Index = 4 });              // ____NodeClassB
node.AddChild(new A { Index = 5 });              // ____NodeClassA
node = tree.Root.AddChild(new A { Index = 6 });  // __NodeClassA
node.AddChild(new C { Index = 7 });              // ____NodeClassC
tree.Root.AddChild(new B { Index = 8 });         // __NodeClassB
tree.Root.AddChild(new C { Index = 9 });         // __NodeClassC 
b0
____C1
____A 2
________b3
________B 4
________A 5
____A 6
________C7
____b8
____C 9

注意,在声明
树节点
类时,您不需要知道
t
的具体数据类型,因为
t
是泛型的。你不妨申报一下

var stringTree = new Tree<string>();
var intTree = new Tree<int>();
var stringTree=newtree();
var intTree=新树();

只要让您的任意类继承或组成某种集合即可。例如,您的任意类都可以是列表。增加的是add方法设置子对象的父对象,父对象是一个属性

只需让您的任意类继承或组成某种集合即可。例如,您的任意类都可以是列表。增加的是add方法设置子对象的父对象,父对象是一个属性

你所做的有什么问题?为什么是不同的课程?它们之间有什么不同吗?您的泛型类缺少
T
的定义:
类MyTreeClass
这个问题是家庭作业吗?如果您确实在寻找包含不同类型的树结构,您可能应该修改示例。从你展示的方式来看,这三种类型都是相同的。你所做的有什么不对?为什么不同的类?它们之间有什么不同吗?您的泛型类缺少
T
的定义:
类MyTreeClass
这个问题是家庭作业吗?如果您确实在寻找包含不同类型的树结构,您可能应该修改示例。按照您呈现的方式,这三种类型都是相同的。