【问题标题】:Traverse a tree from root to all children in Objective-C在Objective-C中从根到所有孩子遍历树
【发布时间】:2015-05-19 05:10:40
【问题描述】:

我想做的一个简化版本是像这样转动一棵树:

变成这样的数组:["abc","abd","ae"]

基本上我想遍历树从它的根节点到每个孩子。

我尝试通过在递归块中放置一个 for-in 循环来做到这一点,但问题是每次递归块时 for 循环都会重新开始。当我尝试异步运行该块时,我不断收到 EXC_BAD_ACCESS

有什么建议吗?

【问题讨论】:

  • downvoter 可以解释一下否决票吗?
  • 投反对票的不是我,但我的猜测是,如果它包含您的代码,以及有关代码失败位置的一些细节,问题会更好。
  • 啊,你是对的。不幸的是,我的代码太复杂了,所以我没有发布它:(

标签: objective-c recursion path tree


【解决方案1】:

假设树是这样表示的:

@interface TreeNode : NSObject
@property(weak,nonatomic) TreeNode *parent;
@property(strong,nonatomic) NSArray *children;
@end

任何节点的沿袭(这是您要查找的)是从根到节点的节点列表。这可以像这样递归定义:

- (NSArray *)lineage {
    if (!self.parent) {
        return @[self];
    } else {
        NSMutableArray *lineage = [[self.parent lineage] mutableCopy];
        [lineage addObject:self];
        return lineage;
    }
}

您正在寻找叶子的谱系,因此我们需要一种收集叶子的方法。如果我们可以遍历树,我们就可以做到这一点。这是一个很好的块应用程序,如下所示:

- (void)depthFirst:(void (^)(TreeNode *))block {
    for (TreeNode *node in self.children) {
        [node depthFirst:block];
    }
    return block(self);
}

这提供了一种自然的方式来收集树叶:

- (NSArray *)leaves {
    NSMutableArray *leaves = [@[] mutableCopy];
    [self depthFirst:^(TreeNode *node) {
        if (!node.children) [leaves addObject:node];
    }];
    return leaves;
}

把它放在一起,我们得到:

- (NSArray *)lineagesOfLeaves {
    NSMutableArray lineages = [@[] mutableCopy];
    for (TreeNode *leaf in [self leaves]) {
        [lineages addObject:[leaf lineage]];
    }
    return lineages;
}

这些方法适用于树中的任何节点。不过,对于您的问题,您需要将 lineagesOfLeaves 发送到树的根。

【讨论】:

  • 您确实应该将parent 属性设为weak 而不是strong。否则你有循环强引用,因为数组保持对子节点的强引用。
  • 感谢您的回答!尚未根据我的具体问题对其进行调整,但它在更简单的试验中起作用。
  • @danh 你能解释一下 depthFirst 方法的工作原理吗?我认为它在最深的叶子上运行一个块,这是正确的吗?如果在运行时递归它包含的方法,for 循环会发生什么?它最终会完成运行吗?
  • @Bogidon - depthFirst 访问接收器及其每个后代,包括内部节点和叶子。如果你在根上调用它,它会访问树上的每个节点一次。如果您从块内调用它,递归将起作用,但您最终会一遍又一遍地访问节点。我会避免从 depthFirst 块内部调用 depthFirst。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-03-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多