为啥 .NET 中没有 Tree<T> 类?

Posted

技术标签:

【中文标题】为啥 .NET 中没有 Tree<T> 类?【英文标题】:Why is there no Tree<T> class in .NET?为什么 .NET 中没有 Tree<T> 类? 【发布时间】:2010-10-30 20:01:18 【问题描述】:

.NET 中的基类库具有一些出色的集合数据结构(列表、队列、堆栈、字典),但奇怪的是它不包含任何用于二叉树的数据结构。对于某些算法,例如那些利用不同遍历路径的算法,这是一个非常有用的结构。我正在寻找一个正确编写的免费实现。

我只是瞎了眼,没有找到它……它被埋在 BCL 的某个地方吗?如果没有,有人可以推荐一个用于二叉树的免费或开源 C#/.NET 库吗?最好是使用泛型的。

编辑:澄清我在寻找什么。我对内部使用树的有序字典集合不感兴趣。我实际上对二叉树感兴趣 - 一种公开其结构的二叉树,以便您可以执行诸如提取子树之类的操作,或在节点上执行修复后遍历。理想情况下,可以扩展这样的类以提供专门树的行为(即红/黑、AVL、平衡等)。

【问题讨论】:

同意。我偶尔需要找到(在 O(Log N) 时间内)绑定一个值的两个节点(当在集合中找不到该值时)。例如,集合(树)包含 13 和 17(以及其他),我正在寻找小于和最小大于 16 的最大值。树可以做到这一点,但字典、排序列表和哈希表需要 O(N) . 【参考方案1】:

不,BCL 中没有任何“Tree&lt;T&gt;-like”类型(这也一直让我感到困惑),但here is a good article 将引导您在 C# 中实现自己的类型。

我想您可能会认为基于树的数据结构在 .NET 通常用于的应用程序(商业应用程序、数据移动应用程序等)中不太常用。不过,我同意你的看法,奇怪的是 BCL 根本没有实现。

【讨论】:

【参考方案2】:

您可以使用TreeNode。它不是通用的并且隐藏在 Windows 窗体中并与树视图控件一起使用,但您也可以在其他地方使用它。

【讨论】:

是的,但它只有一个 System.Object ype 的 Tag 属性。没有通用 参数 我总是觉得做这样的事情很奇怪。在您的特定示例中不太明显,但是如果人们经常从依赖项中重新使用类,这可能会导致难以解释的依赖关系,并且如果重新使用的类以意想不到的方式更改,可能会给您带来麻烦依赖版本。 使用它有什么好处?树节点通常没有任何相关的功能。它只包含对孩子和最终父母的引用。没有理由滥用 System.Windows.Forms 类!只需自己编写 - 在一分钟或更短的时间内。【参考方案3】:

我相信 SortedDictionary 作为 log(n) 插入,检索特征是您期望从树数据结构中获得的特征。

http://msdn.microsoft.com/en-us/library/f7fta44c(VS.80).aspx

【讨论】:

【参考方案4】:

SortedSet&lt;T&gt; 实现为二叉搜索树refSortedDictionary&lt;TKey, TValue&gt; 内部使用了SortedSet&lt;T&gt;,所以它也是一个二叉搜索树ref

【讨论】:

不幸的是,这些只是有序映射和列表的简单实现。两者都不利于作为二叉树的重用——这些树结构只是集合的实现细节。我实际上正在寻找一个公开树结构的类。【参考方案5】:

您希望从这样的实现中得到什么?

二叉树? 红黑? 萝卜树? B树? R树? R*-树?

树与其说是数据结构,不如说是一种模式,它们往往被用在性能很重要的地方(因此实现细节可能也很重要)。如果 BCL 包含某种树类,则无论如何您只需要滚动自己的类

【讨论】:

问题中“为什么”部分的最佳答案。 这些只是搜索树。还有表达式树、决策树…… 确实,实现细节很重要。就我而言,我希望实现一些算法,作为一系列转换的一部分,对有组织的数据集执行不同的遍历(中缀、后缀)。树结构是解决我的问题的最优雅的方式。 在平行宇宙中,有人问这个问题:“为什么 .Net 中没有列表类型?”,他们得到了答案:“你想从这样的实现中得到什么?一个数组?链表?队列?字典?”我认为这是一个不合逻辑的答案。【参考方案6】:

你可以自己定义:

public class MyTree<K, V> : Dictionary<K, MyTree<K, V>>

    public V Value  get; set; 

或无键:

public class MyTree<V> : HashSet<MyTree<V>>

    public V Value  get; set; 

【讨论】:

这需要你知道在编译时你将处理多少个树级别,我错了吗? 不,C# 编译器支持这种语法。 注意元素是这样无序的 @Veverke 也许您在考虑 C++ 模板。 .NET 泛型是运行时类型。 使其成为继承自 System.Collections.Specialized.OrderedDictionary 的有序树【参考方案7】:

当我不得不写自己的文章时,这一系列文章对我很有帮助,尤其是第 3 部分和第 4 部分。

An Extensive Examination of Data Structures

【讨论】:

【参考方案8】:

你是对的,BCL 中没有任何内容。我怀疑这是因为选择是否使用树通常是实现细节,否则是访问数据的非常规方式。也就是说,您不会说“二分查找元素#37”;相反,你说,“给我找元素 #37”。

但是你看过C5吗?它超级好用,而且他们有几个树实现(1、2、3)。

【讨论】:

C5 支持红黑树而不是 B-Tree。它们是人们应该意识到的差异。 B-Tree 更适合基于磁盘的树或基于大内存的树。更多节点保持在同一位置,因此您可以获得更好的处理器缓存性能并更快地读取写入磁盘。

以上是关于为啥 .NET 中没有 Tree<T> 类?的主要内容,如果未能解决你的问题,请参考以下文章

为啥 ConcurrentBag<T> 在 .Net (4.0) 中这么慢?我做错了吗?

为啥 List<T> 在 .NET 4.5 中实现 IReadOnlyList<T>?

为啥 HashSet<T> 没有实现 ICollection?

B-Tree - 为啥没有偶数个键的节点?

为啥对 List<T> 的迭代没有从 SQL 视图中给我正确的值? [复制]

为啥 `IList<T>` 不从 `IReadOnlyList<T>` 继承?