真情大放送:一个兼容STL的tree容器
经过这几天的奋战,beta版终于出来了,我下面将贴出所有代码。希望朋友能在各种平台下试用测试,并将意见反馈给我,以尽快修正。
代码较长,CSDN也不太贴代码,估计比较费劲。
先贴一段说明文字:
关于tree的说明(freefalcon 2004.11.14)
1. STL没有提供树(tree)容器,尽管map等内部是用红黑树(rb_tree)实现的,但rb_tree未被开放出来,而且rb_tree是平衡二叉搜索树,它会自动对元素排序,不能满足一般意义上的树操作。鉴于我自己以及很多朋友有这个需求,我便利用空余时间写了这个tree容器。
2. 这是一个符合STL规范的通用容器,符合数据结构中树的概念,能够满足一般的关于树的操作。目前发布的是beta版,我只在VC6.0和GCC上做过测试,欢迎各位朋友试用该容器,如果您发现任何问题(比如代码有bug或者在某个编译器下不能正常使用)以及有任何建议(比如某个算法可以改进或者需要增加某种方法),请发email到freefalcon@gmail.com,我很乐意接受您的意见和建议。
3. 我自己将tree的代码放在名为tree.hpp的文件中,我建议您也这样做。tree被封装在plux名字空间中,plux意为Portable Lightweight Utility Library(X是为了便于发音),这是我正在开发的一个开源C++库,tree只是其中的一部分,我公布的tree代码实际上包含了其它内容,比如其中的pre_upper_bound是一个独立的STL扩充算法。
4. tree要求只有一个唯一的根节点,但所提供的方法(insert_sibling)不能阻止你为根节点添加一个兄弟节点(这就叫做森林forest了),没有阻止的缘由是允许按从下至上(即从叶结点到根节点)的方式建立一棵树。但树的逻辑是只有一个唯一的根,我提供的方法也是基于此种假设,因此当root有sibling时调用某些方法会出错或者得不到预期的效果。不过我还是在拷贝构造、赋值运算以及clear方法中考虑了这种情况,以符合这三者的语义。
5. tree中提供的depth静态方法用来获得一个节点相对于根节点的深度,关于深度depth有两种不同的定义(至少我看过的数据结构书如此),差别就是根节点的深度是为0还是为1,我采用的是前者。tree的高度height则为树的最大深度加1。
6. tree的allocator被设计成这样,主要是为了搭载GCC的内部内存配置器(高效安全),而在其它编译器下则简单的使用::operator new和::operator delete进行内存的分配与释放。但GCC对内部配置器做过一次更名,我发现GCC3.0.4以前为alloc,GCC3.1以后为__alloc,因此我对此作了自动判断,但我尚不能完全确定就是在GCC3.1开始做的更改,也不能确定是否还有其它编译器使用了这样高效的内存配置策略,也许我可以搭载它,:)
7. tree采用的是child-sibling的动态存储结构,每个节点含有三个指针m_parent、m_child和m_sibling,这决定了其迭代器的--操作很低效,除非再增加一个指向前一个sibling的指针,但空间的增加会带来多大的好处?个人认为operator--操作在树中用得不是很多,因此tree的iterator的类型为ForwardIterator
8. tree的iterator长成这幅德性主要是为了支持对子树(sub tree)进行遍历,你最好使用其中的begin和end方法来确定遍历操作的起点和终点。同时,我提供了各种遍历方式的迭代器,这些迭代器可以互相转换,tree的第二个模板参数用于指定树默认的迭代器类型,但你也可以通过tree的内部定义随时使用其它遍历方式的迭代器。整个traversal iterator架构的设计还有待完善,因为目前我尚未开始二叉树(binary tree)以及其它非线性容器的编写。
9. tree提供了insert、erase、sort、unique等方法,其中insert类方法占的分量较大,以方便用户使用。我的疑问:这些方法是否都必要,或者,还有没有需要增加的方法,比如find,remove(按值删除)等,这里要考虑两个原则:一是完备性,即所有的功能都能够直接或者间接实现,二是接口最小化,尽量无冗余,但又要考虑用户的易用度,这有时就让人难以权衡,比如是否有必要让tree提供内置的find,还是让用户自己通过find范型算法实现?
10. 我还为tree提供了专门的遍历操作方法如tree_preorder_traverse等,这些方法都具有两个版本,版本一采用普通函数或者仿函数来访问节点,版本二要求用户的数据结构要采用Visitor模式。应该还存在其它形式,但我现在接触到的不是很多,因此无法进行一般性的总结。
11. ......