【发布时间】:2009-07-30 15:44:28
【问题描述】:
我编写二叉搜索树模板有两个原因 - 学习 C++ 和学习最常见的算法和数据结构。
所以,问题来了——只要我想实现迭代器,在我看来,对于树的结束位置没有严格的定义。你有什么建议?我该怎么做?
【问题讨论】:
标签: c++ data-structures iterator binary-tree
我编写二叉搜索树模板有两个原因 - 学习 C++ 和学习最常见的算法和数据结构。
所以,问题来了——只要我想实现迭代器,在我看来,对于树的结束位置没有严格的定义。你有什么建议?我该怎么做?
【问题讨论】:
标签: c++ data-structures iterator binary-tree
对于树,有遍历树的标准,即枚举节点:前序遍历、中序遍历和后序遍历。我不会在这里描述所有这些,而是将您重定向到http://en.wikipedia.org/wiki/Tree_traversal。这些概念主要应用于二叉树,但您可以通过添加更多案例将这个想法扩展到任意树:有效地,处理一个节点然后递归,递归然后处理一个节点,处理所有子节点然后递归到每个......等等。据我所知,这种方法没有规范的分类。
【讨论】:
std::map),以及矩阵和许多其他的行/列迭代器。 C++ 标准库通常每个容器只有一种类型的迭代器(不包括反向迭代器)的唯一原因仅仅是时间压力和它对标准化委员会意味着的额外工作。但是,是的,根据 STL 背后的理念,定义多个迭代器类型是可以的。
在编写迭代器时,您必须保持清楚 - 数据结构的迭代器提供对集合的访问作为线性项目序列。某些集合,如数组、列表和队列,自然兼容被视为线性序列。其他类型的集合——树、字典、图表——不一定有一个线性列表的简单解释。事实上,多种解释通常都是有效的。
为像树这样的集合编写迭代器时,您真正要做的是解决以下问题:
无论您选择什么,您都应该非常清楚如何命名(和记录)您的迭代器,以使其访问和发出节点的方式一目了然。
您可能需要为您打算支持的不同类型的遍历编写多个迭代器。这里有一些好文章讨论tree traversal models。
【讨论】:
如果你所说的“严格”是指:一个包罗万象的定义,你是对的,没有一个。
但树的“结束”定义非常明确,尽管取决于您选择的遍历方法。
end。end,等等。end 等。最常见的tree traversal 方法。
【讨论】:
您对迭代器的定义略有错误。迭代器不会从 start 到 finish,也不会从 front 到 back。相反,它们遍历该结构的所有成员。
如果您要求对有序结构(即数组、链表等)进行迭代,您将(通常)按顺序返回成员。
对于无序的项目,例如一个集合,你会得到它们集合迭代器想要给你它们的任何顺序,但你会得到它们,一次一个,就像你一样使用数组迭代器。
至于树,其他人已经提到过:它们有明确定义的全序概念,您只需选择一个即可:)
【讨论】:
这取决于您想对树做什么 - 例如,拥有广度优先搜索或深度优先搜索(或两者)迭代器可能会很好。
如果你有某种特定的方法来擦树,那么实际上你确实有一个开始和一个结束。它不像列表和集合中的线性关系那么明显,但如果你想对其施加一些排序,它就在那里。
【讨论】:
在这种情况下尤其是是有意义的,因为为您的类的用户提供了一种方法,可以根据情况需要以不同的方式轻松遍历所有元素。没有它们,用户需要自己编写复杂的、通常是递归的方式。与例如相比迭代器比使用 for(i=0;i) 更多类型的向量
【讨论】:
我认为在迭代器中以更抽象的方式。我没有在迭代器模式中看到任何真正说明有开始或结束的东西!那么,为什么要受限于这种愿景。我们可以想象只关注下一个元素的迭代器,仅此而已。我的意思是,我遇到过(特别是在大规模处理中)这样的情况,从一开始我们不知道集合的扩展,我们不知道它是否会在某一天结束,或者我们没有他们的所有元素加载到内存中,我们不在乎。我们只关心获取下一个元素。在其中一个实现中,下一个节点是在调用下一个元素方法之后创建的。我们可以敞开心扉思考无限的集合(归根结底,集合是一种数学集合),比如所有数字的集合,所有随机数的集合。您实际上不必将所有元素都保存在内存中(这对于无限集合来说很明显)。当然这不是实际的例子,但我的信息是迭代器的用户不必依赖集合的实际结构或扩展。给我下一个(如果你有的话)。
【讨论】: