使用Objective-C,有没有办法将树转换为快速枚举?

时间:2012-09-06 14:11:43

标签: objective-c ios fast-enumeration

如果有一个具有rootNode的树,并且它的子节点(二叉树)指向左右,是否可以像Objective-C一样将其转换为快速枚举2.0?所以我们可以做到

for (id node in [tree allNodes]) {
    // do something
}

最好不使用NSMutableArrayNSSetNSDictionary等集合对象构建内存大小的O(n)对象。

顺序并不重要,但它可能会以深度优先顺序出现。

3 个答案:

答案 0 :(得分:2)

实现快速枚举时,不必一次返回所有元素。当然,如果一次返回一个,你得到的只是快速枚举语法,没有太多的性能优势。

每次调用countByEnumeratingWithState:objects:count时都可以返回一个元素,或者可以返回所有元素,甚至只返回N个元素。

例如,假设你有一棵大树。您可以使用传递给您的堆栈缓冲区及其长度:

NSUInteger numItemsToReturn = MIN(100, lengthOfStackBuffer);

然后,您可以继续将树遍历到numItemsToReturn或直到到达树的末尾。

内部基础设施将继续致电countByEnumeratingWithState:objects:count,直到它“看到”正确数量的元素。

但请注意,如果您只返回部分数据,则必须在state中存储信息,以便下次知道在哪里恢复。这就是extra的用途。

修改

在原帖上看到你的评论...如果你想支持快速枚举,那么就像上面提到的那样,这很容易。

但是,如果您只想遍历树来执行操作,则可能需要考虑枚举API。例如:

-(void)enumerateWithOptions:(MyTreeEnumerationOptions)options
                 usingBlock:^(id object, unsigned int level, BOOL isLeaf, BOOL *stop)block {
    // In here, you can use the options to determine if you are doing
    // pre/post depth first search, breadth-first, reverse, even concurrent.
    // You also provide an easy way to communicate to the caller not only the
    // object at this node, but the tree-depth of this node, whether it is a
    // leaf, and anything else you want to communicate.
}

然后用户可以致电:

[tree enumerateWithOptions:PreOrderDepthFirst
                usingBlock:^(id object, unsigned int level, BOOL isLeaf, BOOL *stop) {
    // Execute whatever code you want with this object...
    // Set *stop = YES to abort the enumeration.
}];

答案 1 :(得分:1)

正如Jody和waldrumpus所说,你应该遵守NSFastEnumeration。这将允许你写:

for (id node in tree) {
    // do something
}

除此之外,还有许多方法可以枚举,即遍历你的树:首先考虑深度(预订,顺序,后序)或宽度。您可以对树进行子类化,并提供委托方法countByEnumeratingWithState:objects:count的不同实现,或者(更好)具有typedef和属性,该类描述如何遍历树并在委托方法中对此进行处理。

答案 2 :(得分:1)

如果您想以多种方式(前,中,后)遍历树,您可能还会考虑创建自己的NSEnumerator子类,而不是仅仅符合NSFastEnumeration

因此,创建NSPreorderEnumerator,NSInorderEnumerator和NSPostOrderEnumerator子类,它们知道如何遍历树。

然后让树对象通过返回为您的树创建的新枚举器来回复-preorderEnumerator-inorderEnumerator-postorderEnumerator

然后你可以做

for(id node in [tree preorderEnumerator]) {
    // do stuff
}

for(id node in [tree postorderEnumerator]) {
    // do stuff
}

NSArray执行与-reverseObjectEnumerator类似的操作,允许您反向循环。