请你好 - 这是我的第一个问题 . = P
基本上作为夏季项目,我一直在浏览wikipedia page上的数据结构列表并尝试实现它们 . 我上学期参加了一门C课程并发现它非常有趣,作为我实施二项式堆的最后一个项目 - 这也非常有趣 . 也许我很讨厌,但我喜欢数据结构 .
无论如何,足够的背景故事 . 项目进展顺利,我从二叉树开始 . 为了更进一步,我需要创建迭代器来遍历树 . 我已经决定为每个遍历方法(常规迭代器和常量迭代器)创建两种类型的迭代器,我只是不知道如何做到这一点 . 我听说从stl的迭代器继承,甚至使用boosts iterator_facade(这似乎是个不错的选择)
我还没有尝试编写迭代器代码,因为我不知道从哪里开始,但我确实在github上有我当前的代码 . 你可以看一下here .
如果你反对github,我会粘贴相关的类定义 . 这些功能的实现实际上没有任何帮助,但如果您出于某种原因需要它们,请告诉我 . 此外,节点类具有用于迭代目的的父指针 .
#ifndef __TREES_HXX
#define __TREES_HXX
#include <cstdlib> // For NULL
#include <algorithm> // for std::max
// Node class definition. These nodes are to be used for any
// tree where the structure is
// node
// /\
// left right
// /\ /\
//
// etc., basically two children.
template <typename T>
class Node
{
public:
T data_;
Node<T>* left_;
Node<T>* right_;
Node<T>* parent_; // Needed for iterators
explicit Node(T const&);
Node(Node<T> const&);
};
template <typename T>
class BinaryTree
{
protected:
typedef Node<T>* node_t;
size_t tree_size;
public:
typedef T value_type;
explicit BinaryTree();
explicit BinaryTree(T const&);
~BinaryTree();
virtual node_t insert(node_t&, T) = 0;
virtual T& lookup(node_t const&, T const&) const = 0;
inline virtual size_t size() const;
inline virtual size_t depth(node_t const&) const;
inline bool empty() const;
inline void clear(node_t);
node_t root;
};
这是我们抽象类的基本二叉树扩展,基本上它(将是)一个BST . 有关我需要迭代器的原因的示例,请查看查找函数的定义 . 它应该将迭代器返回到找到东西的节点 .
/* Implementation of our Binary Tree is in
* this file. The node class is in Trees.hxx
* because it's intended to be a general class.
*/
#ifndef __BINARY_TREE_HXX
#define __BINARY_TREE_HXX
#include "Trees.hxx"
template <typename T>
class BiTree : public BinaryTree<T>
{
private:
typedef typename BinaryTree<T>::node_t node_t;
public:
typedef typename BinaryTree<T>::value_type value_type;
BiTree() : BinaryTree<T>()
{
}
BiTree(T const& data) : BinaryTree<T>(data)
{
}
node_t insert(node_t&, T);
T& lookup(node_t const&, T const&) const; // Note: This should return an iterator to the node where the stuff is found
};
我想就是这样 - 谢谢你的时间!如果您需要其他信息,请告诉我们 .
2 回答
1.胖迭代器与精益迭代器
有两种可能的方法来实现树的遍历 . 你可以:
有简单指向其"children"的节点,以及保持堆栈的迭代器(因此,胖迭代器)
有节点有父指针(和你的一样),迭代器只是指向给定节点的指针(精益迭代器)
这是一个设计权衡,STL实现者通常采用精益方式,因为迭代器(在STL中)应该是便宜的复制 .
还有几种方法可以实现迭代器:
From Scratch:你自己做所有事情,包括定义typedef,所有运算符重载等等......
简单:您使用Boost.Iterator自己实现尽可能少的代码
我基本上计算从
std::iterator
继承为"from scratch"情况,因为它只提供了5typedef
...是否选择其中一个确实取决于您的情况:
出于学习目的,我建议多次使用"From Scratch"方式
出于 生产环境 目的,我建议采用"From Scratch"方式(从Boost继承并不节省太多,但它确实使调试会话/内存转储复杂化,至少使用gdb,因为gdb暴露了基类)
为了快速测试,我建议采用"Easy"方式
请注意,您可能处于一个奇怪的情况,您的迭代器无法真正构建在Boost.Iterator之上,在这种情况下,您将别无选择,只能自己构建它 .
这也许是重点 .
如果仅为此,则值得查看Boost.Iterator,因为它们公开了实现 one iterator(模板化)的技术,这将涵盖两种情况 .
查看Iterator Adaptor中的 Tutorial Example 部分:
第3个构造函数是获取一对
const
和非const
迭代器的关键点,它们具有从const
到非const
的自动转换,而无需进行反向转换 .无论你做什么,重用同样的技巧:在
Value
上模板化BaseIterator
,并提供两个typedef:typedef BaseIterator<Value> iterator
和typedef BaseIterator<Value const> const_iterator
.实现此目的的一种方法是在迭代器中使用堆栈来跟踪父节点 . 每次到达节点时,它都不是叶子,将其推入堆栈并继续搜索顺序中的下一个节点 . 一旦你点击一个叶子,处理它,然后返回到堆栈顶部的节点 . 重复广告nausium直到你访问过所有内容 .