【发布时间】:2013-10-21 16:31:23
【问题描述】:
考虑一个层次树结构,其中一个项目可能有兄弟项目(在层次结构中的同一级别),也可能有子项目(在层次结构中向下一级)。
假设结构可以定义为:
// an item of a hierarchical data structure
struct Item {
int data; // keep it an int, rather than <T>, for simplicity
vector<Item> children;
};
我希望能够在此结构上使用算法,例如 std::map、std::vector 等的算法。因此,我创建了一些算法,例如:
template <class Function>
Function for_each_children_of_item( Item, Function f ); // deep (recursive) traversal
template <class Function>
Function for_each_direct_children_of_item( Item, Function f ); // shallow (1st level) traversal
template <class Function>
Function for_each_parent_of_item( Item, Function f ); // going up to the root item
困扰我的一件事是同一个结构有 3 个for_each() 函数。但是他们很好地描述了他们如何迭代,所以我决定接受它。
然后,很快就出现了对更多算法的需求(如find_if、count_if、any_of 等),这让我觉得我在设计方面没有走上正轨。
我能想到的一种可以减少工作量的解决方案是简单地编写:
vector<Item> get_all_children_of_item( Item ); // recursive
vector<Item> get_all_direct_children_of_item( Item ); // 1st level items
vector<Item> get_all_parents_of_item( Item ); // up to the root item
然后我可以使用所有的 STL 算法。 我对这个解决方案有点警惕,因为它涉及复制。
我想不出实现iterator 的方法,因为在递归版本的遍历中没有明显的end() 迭代器。
- 谁能提出一种典型/惯用的方法来处理这种非线性数据结构?
- 可以/应该为这样的结构创建迭代器吗?怎么样?
【问题讨论】:
-
std::map采用迭代器路由。它确实适用于树,但我不是谷歌工作面试的专家,所以我现在没有记住任何无用的树算法。 :) 您的直觉是正确的,因为您想要查看数据,而不是数据的副本。所以我会专注于研究如何在树上从左到右工作。 :) -
是的,迭代器在这里是合适的。例如,这就是您将算法应用于
std::map的内容的方式,即使它是作为二叉树实现的。无需复制数据;只需在增量运算符中编写适当的遍历代码即可。 -
Map 可以迭代,因为它有指向父节点的指针。可以在不向结构添加额外数据的情况下完成吗?我无法更改这部分代码。
-
对于
std::map,树对用户是隐藏的。对于迭代,它的行为就像一个“平面”容器(例如,像一个链表)。如果您想迭代树中类似于std::map的所有节点,您可以查看libstdc++ 的_Rb_tree_increment,它实现了std::map的迭代。 -
@Grim 如果您无法更改结构,您可能必须在迭代器中存储额外的状态 - 例如从根目录到您所在位置的路径中的所有
Items。