关于树型结构与泛型,在线等

enaking 2020-10-11 03:01:48
大家好,最近我想写一个树型结构和泛型结合起来的一个东西
在我思路中,有Tree和TreeNode两个类,Tree类描述整个树型结构及方法,而TreeNode类代表其中一个节点。但我的节点是想适用到未来开发的各种类中。所以要用到泛型。现在我就比较乱,不知道怎么架构。始终理不清Tree、TreeNode与泛型的结合。对泛型写法不太了解。

并且后期我会把递归等常用的集成到里面,并且在递归中委托事件出去完成个性化业务。如下(代码写法不一定正确,只是想说清楚我的想法): 谢谢大家给个关键点的思路

Recurrence(T node)
{
foreach (nodeEach in node.Nodes )

委托事件ing
Recurrence(nodeEach )
委托事件ed

}
...全文
1748 12 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
12 条回复
切换为时间正序
请发表友善的回复…
发表回复
qq77618 2020-10-12
  • 打赏
  • 举报
回复
学习到了,谢谢前辈的分享
threenewbee 2020-10-12
  • 打赏
  • 举报
回复
class Tree<T>
{
public Node<T> root;
}
class Node<T>
{
public T value;
public List<Node<T>> children;
}
wanghui0380 2020-10-12
  • 打赏
  • 举报
回复
这样把,我给个例子你就明白了
  public static class Linq
    {
        public static IEnumerable<T> Flatten<T>(this IEnumerable<T> source, Func<T, IEnumerable<T>> selector)
        {
            foreach (var x1 in source)
            {
                yield return x1;

                var res = selector(x1);
                foreach (var re in res)
                {
                    yield return re;
                }
            }

        }
    }
调用
TreeView tv = new TreeView();

            TreeNode node1 = new TreeNode("A");
            TreeNode node2 = new TreeNode("A1");
            node1.Nodes.Add(node2);

            

            tv.Nodes.Add(node1);

            var nodes = tv.Nodes.Cast<TreeNode>();

           var Flatten_nodes= nodes.Flatten(p => p.Nodes.Cast<TreeNode>());

           //打印所有的
            foreach (var flattenNode in Flatten_nodes)
            {
                Console.WriteLine(flattenNode.Text);
            }
你看这个调用过程,我们压根就不关心他是treeview还是treenode,我只是需要 odes.Flatten(p => p.Nodes.Cast<TreeNode>()). 你告诉我怎么找到下一级的IEnumerable<TreeNode>
正怒月神 2020-10-12
  • 打赏
  • 举报
回复
引用 7 楼 enaking 的回复:
[quote=引用 3 楼 wanghui0380 的回复:]无需任何多余的思考和封装,因为根本就不需要。你只关心nodes就好,tree不tree那是外观,同时所谓的node都是多余的,因为任何层级其实都是 ienumerable<T> ,我们不关心什么children不children,你只需要和slectmany一样告诉们下一步的ienumerable<T>怎么找就好 所以linq,selectmany本身就是。如果你觉着非要是个“树”,那么自己写个扩展方法写成HierarchicalSelectMany方法也未尝不可 https://www.google.com.hk/search?newwindow=1&safe=strict&source=hp&ei=UKWDX6maNpK5mAX6j4OgCw&q=C%23+linq+hierarchical+selectmany&oq=C%23+linq+hierarchical+selectmany&gs_lcp=CgZwc3ktYWIQAzoCCAA6BAgAEB46BggAEAcQHjoECAAQDToICAAQBxAeEBM6BAgAEBM6BggAEB4QEzoICAAQCBAeEBM6BggAEA0QHjoHCCEQChCgAVCWD1i1emCdfWgBcAB4AIABxgSIAbkzkgEKMi0xOC4yLjAuMpgBAKABAqABAaoBB2d3cy13aXo&sclient=psy-ab&ved=0ahUKEwipgpaK6K3sAhWSHKYKHfrHALQQ4dUDCAc&uact=5 我用google搜索了,这玩意就别相信百度了,博客园那波人还瞧不起这东西,不屑一写。(唯独写了这东西的是sp1234的“重量级查询控件”,这帖子你百度可以找到,我就不废那个力了) 来给我google的老外的扩展方法
public static class Linq
{
    public static IEnumerable<T> Flatten<T>(this T source, Func<T, IEnumerable<T>> selector)
    {
        return selector(source).SelectMany(c => Flatten(c, selector))
                               .Concat(new[] { source });
    }
}
看明白了么,我们不关心啥tree,啥nodes,我们关心的是 hierarchical 层级数据,Flatten 扁平查询
引用 3 楼 wanghui0380 的回复:
无需任何多余的思考和封装,因为根本就不需要。你只关心nodes就好,tree不tree那是外观,同时所谓的node都是多余的,因为任何层级其实都是 ienumerable<T> ,我们不关心什么children不children,你只需要和slectmany一样告诉们下一步的ienumerable<T>怎么找就好 所以linq,selectmany本身就是。如果你觉着非要是个“树”,那么自己写个扩展方法写成HierarchicalSelectMany方法也未尝不可 https://www.google.com.hk/search?newwindow=1&safe=strict&source=hp&ei=UKWDX6maNpK5mAX6j4OgCw&q=C%23+linq+hierarchical+selectmany&oq=C%23+linq+hierarchical+selectmany&gs_lcp=CgZwc3ktYWIQAzoCCAA6BAgAEB46BggAEAcQHjoECAAQDToICAAQBxAeEBM6BAgAEBM6BggAEB4QEzoICAAQCBAeEBM6BggAEA0QHjoHCCEQChCgAVCWD1i1emCdfWgBcAB4AIABxgSIAbkzkgEKMi0xOC4yLjAuMpgBAKABAqABAaoBB2d3cy13aXo&sclient=psy-ab&ved=0ahUKEwipgpaK6K3sAhWSHKYKHfrHALQQ4dUDCAc&uact=5 我用google搜索了,这玩意就别相信百度了,博客园那波人还瞧不起这东西,不屑一写。(唯独写了这东西的是sp1234的“重量级查询控件”,这帖子你百度可以找到,我就不废那个力了) 来给我google的老外的扩展方法
public static class Linq
{
    public static IEnumerable<T> Flatten<T>(this T source, Func<T, IEnumerable<T>> selector)
    {
        return selector(source).SelectMany(c => Flatten(c, selector))
                               .Concat(new[] { source });
    }
}
看明白了么,我们不关心啥tree,啥nodes,我们关心的是 hierarchical 层级数据,Flatten 扁平查询
我参考了一下treeview控件中的node结构,里面是一个TreeNode加一个TreeNodeCollection,所以我现在纠结中[/quote] 这个意思?
static void Main(string[] args)
        {
            //初始化T
            User user = new User() { Name = "tyler", Age = 2 };
            //创建node,并且实现act委托
            Node<User> node = new Node<User>();
            node.data = user;
            node.act = (x) => Console.WriteLine($"{x.Name}--{x.Age}");
            //调用
            node.ToDo();    //tyler--2

            //创建 child
            User user1 = new User() { Name = "t1", Age = 10 };
            Node<User> node1 = new Node<User>();
            node1.data = user1;
            node.Child = node1;
            node.Child.ToDo();  //t1--10

            Console.ReadLine();
        }

        public class Node<T>
        {
            public int Key { get; set; }
            public string Value { get; set; }
            public T data { get; set; }

            private Node<T> child;
            public Node<T> Child
            {
                get { return child; }
                set
                {
                    child = value;
                    //默认赋值act动作
                    if (child.act == null)
                        child.act = act;
                }
            }

            public Action<T> act;

            public void ToDo()
            {
                if (act != null)
                    act(data);
            }
        }
enaking 2020-10-12
  • 打赏
  • 举报
回复
引用 4 楼 wanghui0380 的回复:
上面是层级到扁平,同样的思路我们可以反向写扁平到层级的扩展方法。当然我们依然不关心啥tree和nodes 因为除非微软能给你统一 一个所谓的IHierarchicalData接口,否则都是白搭。因为tree是外观,我说菜单也是外观,sp1234说control也是外观。 微软没给统一层级描述接口,那么各家都自己弄。最后是web的treeview有自己的东西,winform的有自己的东西,control还有自己的东西。你自己在搞个你自己的东西? 所以我们依旧不封装,也无法封装。只能用外观,用访问者写临时扩展。这个不值得统一
我不是写一个外观,是数据结构,很多不同的对象,其集合起来是一个树的结构,如地区,部门,我就想把树结构的特性用在不同的对象上。
enaking 2020-10-12
  • 打赏
  • 举报
回复
引用 3 楼 wanghui0380 的回复:
无需任何多余的思考和封装,因为根本就不需要。你只关心nodes就好,tree不tree那是外观,同时所谓的node都是多余的,因为任何层级其实都是 ienumerable<T> ,我们不关心什么children不children,你只需要和slectmany一样告诉们下一步的ienumerable<T>怎么找就好 所以linq,selectmany本身就是。如果你觉着非要是个“树”,那么自己写个扩展方法写成HierarchicalSelectMany方法也未尝不可 https://www.google.com.hk/search?newwindow=1&safe=strict&source=hp&ei=UKWDX6maNpK5mAX6j4OgCw&q=C%23+linq+hierarchical+selectmany&oq=C%23+linq+hierarchical+selectmany&gs_lcp=CgZwc3ktYWIQAzoCCAA6BAgAEB46BggAEAcQHjoECAAQDToICAAQBxAeEBM6BAgAEBM6BggAEB4QEzoICAAQCBAeEBM6BggAEA0QHjoHCCEQChCgAVCWD1i1emCdfWgBcAB4AIABxgSIAbkzkgEKMi0xOC4yLjAuMpgBAKABAqABAaoBB2d3cy13aXo&sclient=psy-ab&ved=0ahUKEwipgpaK6K3sAhWSHKYKHfrHALQQ4dUDCAc&uact=5 我用google搜索了,这玩意就别相信百度了,博客园那波人还瞧不起这东西,不屑一写。(唯独写了这东西的是sp1234的“重量级查询控件”,这帖子你百度可以找到,我就不废那个力了) 来给我google的老外的扩展方法
public static class Linq
{
    public static IEnumerable<T> Flatten<T>(this T source, Func<T, IEnumerable<T>> selector)
    {
        return selector(source).SelectMany(c => Flatten(c, selector))
                               .Concat(new[] { source });
    }
}
看明白了么,我们不关心啥tree,啥nodes,我们关心的是 hierarchical 层级数据,Flatten 扁平查询
引用 3 楼 wanghui0380 的回复:
无需任何多余的思考和封装,因为根本就不需要。你只关心nodes就好,tree不tree那是外观,同时所谓的node都是多余的,因为任何层级其实都是 ienumerable<T> ,我们不关心什么children不children,你只需要和slectmany一样告诉们下一步的ienumerable<T>怎么找就好 所以linq,selectmany本身就是。如果你觉着非要是个“树”,那么自己写个扩展方法写成HierarchicalSelectMany方法也未尝不可 https://www.google.com.hk/search?newwindow=1&safe=strict&source=hp&ei=UKWDX6maNpK5mAX6j4OgCw&q=C%23+linq+hierarchical+selectmany&oq=C%23+linq+hierarchical+selectmany&gs_lcp=CgZwc3ktYWIQAzoCCAA6BAgAEB46BggAEAcQHjoECAAQDToICAAQBxAeEBM6BAgAEBM6BggAEB4QEzoICAAQCBAeEBM6BggAEA0QHjoHCCEQChCgAVCWD1i1emCdfWgBcAB4AIABxgSIAbkzkgEKMi0xOC4yLjAuMpgBAKABAqABAaoBB2d3cy13aXo&sclient=psy-ab&ved=0ahUKEwipgpaK6K3sAhWSHKYKHfrHALQQ4dUDCAc&uact=5 我用google搜索了,这玩意就别相信百度了,博客园那波人还瞧不起这东西,不屑一写。(唯独写了这东西的是sp1234的“重量级查询控件”,这帖子你百度可以找到,我就不废那个力了) 来给我google的老外的扩展方法
public static class Linq
{
    public static IEnumerable<T> Flatten<T>(this T source, Func<T, IEnumerable<T>> selector)
    {
        return selector(source).SelectMany(c => Flatten(c, selector))
                               .Concat(new[] { source });
    }
}
看明白了么,我们不关心啥tree,啥nodes,我们关心的是 hierarchical 层级数据,Flatten 扁平查询
我参考了一下treeview控件中的node结构,里面是一个TreeNode加一个TreeNodeCollection,所以我现在纠结中
正怒月神 2020-10-12
  • 打赏
  • 举报
回复
你要先明确,这个泛型在你的tree类里,代表的含义是什么? 是一个key,还是value,或者用来做什么呢?
wanghui0380 2020-10-12
  • 打赏
  • 举报
回复
一定要统一的化
public static IEnumerable<Node<T>> Hierarchize<T, TKey, TOrderKey>(
    this IEnumerable<T> elements, 
    TKey topMostKey, 
    Func<T, TKey> keySelector, 
    Func<T, TKey> parentKeySelector, 
    Func<T, TOrderKey> orderingKeySelector)
{
    var families = elements.ToLookup(parentKeySelector);
    var childrenFetcher = default(Func<TKey, IEnumerable<Node<T>>>);
    childrenFetcher = parentId => families[parentId]
        .OrderBy(orderingKeySelector)
        .Select(x => new Node<T>(x, childrenFetcher(keySelector(x))));

    return childrenFetcher(topMostKey);
}


public class Node<T>
{
    public T Value { get; private set; }
    public IList<Node<T>> Children { get; private set; }

    public Node(T value, IEnumerable<Node<T>> children)
    {
        this.Value = value;
        this.Children = new List<Node<T>>(children);
    }
}
其实就有些脱裤子的意思,先聚合到自己的临时Node<T>里,然后在写临外一个Cast 或makeXXXXTree方法在遍历和转换(当然你叫外观模式可以,你想弄成所谓的访问者模式也随便你)
wanghui0380 2020-10-12
  • 打赏
  • 举报
回复
上面是层级到扁平,同样的思路我们可以反向写扁平到层级的扩展方法。当然我们依然不关心啥tree和nodes 因为除非微软能给你统一 一个所谓的IHierarchicalData接口,否则都是白搭。因为tree是外观,我说菜单也是外观,sp1234说control也是外观。 微软没给统一层级描述接口,那么各家都自己弄。最后是web的treeview有自己的东西,winform的有自己的东西,control还有自己的东西。你自己在搞个你自己的东西? 所以我们依旧不封装,也无法封装。只能用外观,用访问者写临时扩展。这个不值得统一
wanghui0380 2020-10-12
  • 打赏
  • 举报
回复
无需任何多余的思考和封装,因为根本就不需要。你只关心nodes就好,tree不tree那是外观,同时所谓的node都是多余的,因为任何层级其实都是 ienumerable<T> ,我们不关心什么children不children,你只需要和slectmany一样告诉们下一步的ienumerable<T>怎么找就好 所以linq,selectmany本身就是。如果你觉着非要是个“树”,那么自己写个扩展方法写成HierarchicalSelectMany方法也未尝不可 https://www.google.com.hk/search?newwindow=1&safe=strict&source=hp&ei=UKWDX6maNpK5mAX6j4OgCw&q=C%23+linq+hierarchical+selectmany&oq=C%23+linq+hierarchical+selectmany&gs_lcp=CgZwc3ktYWIQAzoCCAA6BAgAEB46BggAEAcQHjoECAAQDToICAAQBxAeEBM6BAgAEBM6BggAEB4QEzoICAAQCBAeEBM6BggAEA0QHjoHCCEQChCgAVCWD1i1emCdfWgBcAB4AIABxgSIAbkzkgEKMi0xOC4yLjAuMpgBAKABAqABAaoBB2d3cy13aXo&sclient=psy-ab&ved=0ahUKEwipgpaK6K3sAhWSHKYKHfrHALQQ4dUDCAc&uact=5 我用google搜索了,这玩意就别相信百度了,博客园那波人还瞧不起这东西,不屑一写。(唯独写了这东西的是sp1234的“重量级查询控件”,这帖子你百度可以找到,我就不废那个力了) 来给我google的老外的扩展方法
public static class Linq
{
    public static IEnumerable<T> Flatten<T>(this T source, Func<T, IEnumerable<T>> selector)
    {
        return selector(source).SelectMany(c => Flatten(c, selector))
                               .Concat(new[] { source });
    }
}
看明白了么,我们不关心啥tree,啥nodes,我们关心的是 hierarchical 层级数据,Flatten 扁平查询
ziqi0716 2020-10-12
  • 打赏
  • 举报
回复
只需要一个TreeNode<T>对象就可以了呀,根节点也是个TreeNode嘛
public class TreeNode<T>
{
  public string Name {get;set;}
  public T Data {get;set}
  public TreeNode<T> LeftChild {get;set}
  public TreeNode<T> RightChild {get;set}
//其他方法和属性
}
enaking 2020-10-11
  • 打赏
  • 举报
回复
自己顶一下。。。。。。。。。。。

111,098

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • AIGC Browser
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧