在Objective-C中从根遍历树到所有子级

在Objective-C中从根遍历树到所有子级,objective-c,recursion,path,tree,Objective C,Recursion,Path,Tree,我想做的一个简化版本是像这样转动一棵树: 放入如下数组:[“abc”、“abd”、“ae”] 基本上我想遍历树,从它的根节点到每个子节点 我试着在递归块中放入for循环,但问题是每次递归块时for循环都会重新开始。当我尝试异步运行该块时,我一直获得EXC\u BAD\u访问权限 有什么建议吗?假设树是这样表示的: @interface TreeNode : NSObject @property(weak,nonatomic) TreeNode *parent; @property(strong

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

放入如下数组:[“abc”、“abd”、“ae”]

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

我试着在递归块中放入for循环,但问题是每次递归块时for循环都会重新开始。当我尝试异步运行该块时,我一直获得EXC\u BAD\u访问权限


有什么建议吗?

假设树是这样表示的:

@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);
}
任何节点的沿袭(即您正在寻找的)都是从根节点到节点的节点列表。这可以像这样递归定义:

@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);
}
你在寻找树叶的血统,所以我们需要一种收集树叶的方法。如果我们能穿过这棵树,我们就能做到。这是一个很好的块应用程序,如下所示:

@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;
}

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

假设树是这样表示的:

@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);
}
任何节点的沿袭(即您正在寻找的)都是从根节点到节点的节点列表。这可以像这样递归定义:

@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);
}
你在寻找树叶的血统,所以我们需要一种收集树叶的方法。如果我们能穿过这棵树,我们就能做到。这是一个很好的块应用程序,如下所示:

@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;
}

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

您确实应该将
父属性
设置为弱属性
,而不是
强属性
。否则,由于数组保留对子节点的强引用,因此您将使用循环强引用。谢谢您的回答!还没有调整它以适应我的具体问题,但它在一个更简单的试验中起作用。@danh你能解释一下depthFirst方法是如何工作的吗?我想它在最深的叶子上跑了一个街区,对吗?如果在for循环运行时递归它所包含的方法,它会发生什么情况?它最终会完成运行吗?@Bogidon-depthFirst访问接收器及其每个子体,包括内部节点和叶子。如果在根上调用它,它将访问树上的每个节点一次。如果从块内调用它,递归将起作用,但最终会反复访问节点。我会避免从depthFirst块内部调用depthFirst。您确实应该使
父属性
,而不是
。否则,由于数组保留对子节点的强引用,因此您将使用循环强引用。谢谢您的回答!还没有调整它以适应我的具体问题,但它在一个更简单的试验中起作用。@danh你能解释一下depthFirst方法是如何工作的吗?我想它在最深的叶子上跑了一个街区,对吗?如果在for循环运行时递归它所包含的方法,它会发生什么情况?它最终会完成运行吗?@Bogidon-depthFirst访问接收器及其每个子体,包括内部节点和叶子。如果在根上调用它,它将访问树上的每个节点一次。如果从块内调用它,递归将起作用,但最终会反复访问节点。我会避免在depthFirst区内打电话给depthFirst。downvoter能解释一下down vote吗?不是我在down vote上,但我猜如果包含您的代码,以及一些代码失败的细节,问题会更好。啊,您是对的。不幸的是,我的代码太复杂了,所以我没有发布它:(downvoter能解释一下DownVote吗?不是我在DownVote上,但我猜如果它包括你的代码,以及一些代码失败的细节,问题会更好。啊,你是对的。不幸的是,我的代码太复杂了,所以我没有发布它:(