请保持友好 - 这是我的第一个问题。 = P
基本上作为一个夏季项目,我一直在浏览wikipedia page上的数据结构列表,并试图实现它们。我上学期参加了C ++课程并发现它非常有趣,作为我实施二项式堆的最终项目 - 这也非常有趣。也许我很讨厌,但我喜欢数据结构。
无论如何,足够的背景故事。项目进展顺利,我从二叉树开始。为了更进一步,我需要创建迭代器来遍历树。我已经决定为每个遍历方法(常规迭代器和常量迭代器)创建两种类型的迭代器,我只是不知道如何做到这一点。我听说继承了stl的迭代器,甚至使用了boost 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
};
我认为就是这样 - 感谢您的时间!如果您需要其他信息,请告诉我们。
答案 0 :(得分:12)
1。 Fat Iterators与Lean Iterators
有两种可能的方法来实现树的遍历。你可以:
这是一个设计权衡,STL实现者通常采用精益方式,因为迭代器(在STL中)应该很便宜复制。
2。 Easy Iterators vs From scratch iterators
还有几种方法可以实现迭代器:
我基本上将std::iterator
作为“从头开始”的情况继承,因为它只提供了5 typedef
......
是否选择其中一个确实取决于您的情况:
请注意,您可能处于一种奇怪的情况,您的迭代器无法真正构建在Boost.Iterator之上,在这种情况下,您将别无选择,只能自己构建它。
3。 Const和非const迭代器
这也许是重点。
如果只是为了这个,那么值得关注Boost.Iterator,因为他们公开了实现一个迭代器(模板化)的技术,该技术将涵盖两个案例。
查看Iterator Adaptor中的教程示例部分:
template <class Value>
class node_iter
: public boost::iterator_adaptor<
node_iter<Value> // Derived
, Value* // Base
, boost::use_default // Value
, boost::forward_traversal_tag // CategoryOrTraversal
>
{
private:
struct enabler {}; // a private type avoids misuse
public:
node_iter()
: node_iter::iterator_adaptor_(0) {}
explicit node_iter(Value* p)
: node_iter::iterator_adaptor_(p) {}
/// !!! Highlight !!!
template <class OtherValue>
node_iter(
node_iter<OtherValue> const& other
, typename boost::enable_if<
boost::is_convertible<OtherValue*,Value*>
, enabler
>::type = enabler()
)
: node_iter::iterator_adaptor_(other.base()) {}
private:
friend class boost::iterator_core_access;
void increment() { this->base_reference() = this->base()->next(); }
};
第3个构造函数是获取一对const
和非const
迭代器的关键点,它们可以从const
自动转换为非const
而无需反向转换可能。
无论你做什么,重复使用相同的技巧:在BaseIterator
上模仿Value
,并提供两个typedef:typedef BaseIterator<Value> iterator
和typedef BaseIterator<Value const> const_iterator
。
答案 1 :(得分:1)
实现此目的的一种方法是在迭代器中使用堆栈来跟踪父节点。每次到达节点时,它都不是叶子,将其推入堆栈并继续搜索顺序中的下一个节点。一旦你点击一个叶子,处理它,然后返回到堆栈顶部的节点。重复广告nausium,直到你访问过所有内容。