什么是好的稳定的 C++ 树实现?

Posted

技术标签:

【中文标题】什么是好的稳定的 C++ 树实现?【英文标题】:What's a good and stable C++ tree implementation? 【发布时间】:2008-10-08 07:13:49 【问题描述】:

我想知道是否有人可以推荐一个好的 C++ 树实现,希望是 尽可能兼容 stl。

为了记录,我以前写过很多次树算法,我知道这很有趣,但如果可能的话,我想变得务实和懒惰。因此,此处的目标是与有效解决方案的实际链接。

注意:我正在寻找通用树,而不是平衡树或地图/集,在这种情况下,结构本身和树的连接性很重要,而不仅仅是其中的数据。 所以每个分支都需要能够保存任意数量的数据,并且每个分支都应该是可单独迭代的。

【问题讨论】:

【参考方案1】:

我不知道您的要求,但是如果您主要对结构感兴趣,而不是对特定于树的好处感兴趣,那么使用图表(例如在 Boost Graph 中的实现)会不会更好喜欢通过平衡来提高速度?您可以通过图表“模拟”一棵树,它可能(在概念上)更接近您正在寻找的内容。

【讨论】:

是的,你是对的,我刚看完 Boost::Graph 回来。它似乎适合我的需求(结构),但是文档很大!如果有一个更简单的树版本会很好。 没错,文档令人生畏。如果您真的打算将项目的重要部分建立在此基础上,我建议您获取 boost graph book。它写得很清楚(因为关于这个主题的书可以很清楚)并且相当全面。最重要的是,它能让您快速上手。 我刚刚发布了一个新问题here,询问如何使用 Boost Graph Library 实现这样的树。也许你可以指出我正确的方向?非常感谢! 10 年后,我不确定为什么这是投票率最高的答案。 OP 想要一棵树,答案是使用 Boost Graph,因为“这不是你真正想要的”?即使没有迹象表明 OP 想要一个图表,而不是一棵树。顺便说一句,w.r.t。 Boost Graph:它不是一棵树,但您可以用它构建一棵树,尤其是当您购买一本书以快速上手时。 (我是作为一个已经拥有这本书的人发言。) @davidbak 然而,10 年前,OP 回答说这确实是他正在寻找的东西,而我的回答本身说图不是一棵树,但你可以用它来建一个?不知道你的评论是什么意思......【参考方案2】:

看看this。

C++ 的 tree.hh 库为 n 叉树提供了一个类似于 STL 的容器类,模板化了存储在节点上的数据。提供了各种类型的迭代器(post-order、pre-order 等)。在可能的情况下,访问方法与 STL 兼容,或者可以使用替代算法。

HTH

【讨论】:

看起来不错,但它是 GNU。为一棵树付出的代价是非常沉重的 首先,这个项目不是 GNU 的一部分。其次,如果你谈论 GPL,这并不一定要付出任何代价。这取决于是否要发布代码以及在什么条件下发布。 他在主页上提到如果 GPL 不适合,可以联系他。买一棵树的合理价格是多少?它为您的项目节省了多少工作/时间? @user18044 with tree.hh,是否可以双向移动(从父亲到儿子,从儿子到父亲)? 嗯,它很小,缺乏文档并且速度很慢......我担心的是......为什么它很慢 :(。当然 Boost::BGL 可能会因为分配而令人头疼对于 vector 策略,它确实会在优化后提供纯速度(尽管预分配很痛苦..)。【参考方案3】:

我将建议使用 std::map 而不是树。

一棵树的复杂性特征是:

插入:       O(ln(n)) 移除:O(ln(n)) 查找:         O(ln(n))

这些与 std::map 所保证的特性相同。 因此,std::map 的大多数实现都在底层使用了树(红黑树)(尽管从技术上讲这不是必需的)。

【讨论】:

我认为您的意思是大多数 std::map 实现在幕后使用树。具体来说,许多(大多数?)使用红黑树。 我虽然这是我写的?但我应该注意红黑部分。 (通用)树的好处是您可以将 n 个子节点添加到分支,并将操作应用于不同的分支,但 std::map 将所有这些抽象掉,或者使用红黑(child n=2),并将结构抽象为平面接口。 能够对单个分支进行操作是整点或一棵树。示例可能是文件系统文件夹、数据布局、场景图、语言分析、类似 xml 的结构化数据,可能还有更多我现在想不出来的案例。 但是对于平面数据,是的,你是对的,地图会很好,但我个人更喜欢平面数据的哈希【参考方案4】:

如果您没有(键,值)对,而只是键,请使用 std::set。它使用与 std::map 相同的红黑树。

【讨论】:

【参考方案5】:

好的,伙计们,我找到了另一个树库; stlplus.ntree。但是还没试过。

【讨论】:

【参考方案6】:

假设问题是关于平衡的(以某种形式,主要是红黑树)二叉树,即使事实并非如此。

平衡的二叉树,比如向量,允许管理元素的一些排序,而不需要任何键(比如通过在向量中的任何位置插入元素),但是:

对一个元素的所有修改具有最佳 O(log(n)) 或更好的复杂性(在开始时添加/删除,在任何迭代器之前和之后结束) 除了直接破坏迭代器指向的元素外,通过任何修改实现迭代器的持久性

可选地,可以支持像向量中的索引访问(按元素计算一个 size_t 的成本),复杂度为 O(log(n))。如果使用,迭代器将是随机的。

可选的顺序可以通过一些比较函数来强制执行,但迭代器的持久性允许使用不可重复的比较方案(例如:交通堵塞期间任意车道改变)。

在实践中,平衡二叉树具有向量、列表、双链表、映射、多映射、双端队列、队列、优先级队列...的接口,对于所有单元素操作都达到了理论上的最优 O(log(n)) 复杂度。

这大概就是c++ stl不提出的原因吧

个人可能不会自己实现一般的平衡树,因为难以正确管理平衡,尤其是在元素提取期间。

平衡二叉树没有广泛可用的实现,因为最先进的红黑树(此时由于移除期间代价高昂的固定数量的树重组而成为最佳的平衡树类型)知道实现,每个人都盲目地复制结构发明者的初始代码中的实现者不允许迭代器持久性。这可能是缺少全功能树模板的原因。

【讨论】:

以上是关于什么是好的稳定的 C++ 树实现?的主要内容,如果未能解决你的问题,请参考以下文章

C++ - 区间树实现

对 C++ 哈希表有一个好的哈希函数吗?

什么是好的数据库模型定义语言?

什么是好的API与设计流程和设计原则

为啥将脚本标签放在正文标签的末尾是好的?

一个故事告诉你什么才是好的程序员