How to track the depth in this object graph depth-first search algorithm?

混江龙づ霸主 提交于 2020-02-03 09:41:25

问题


I have this code which iterates over a tree, doing a depth-first search. Every element is tackled exactly once. Very good.

-(void)iterateOverTree:(TreeNode *)node
{
    NSMutableArray * elements = [NSMutableArray array];
    [elements addObject:node];

    while([elements count])
    {
        TreeNode * current = [elements objectAtIndex:0];
        [self doStuffWithNode:current];
        for(TreeNode * child in current.children)
        {
            [elements addObject:child];
        }

        [elements removeLastObject];
    }
}

BUT: How can I keep track of the current depth in the graph? I need to know the level of depth. So for example I have these nodes:

A has childs B, J. B has child C. C has child D. D has childs E, F, I.

When A is at depth level 1, then B is 2 and C is 3.

With recursion it was very easy to keep track of the current depth level. Just inrement a variable before calling itself and decrement it after calling itself.

But here with this fancy while loop that is not possible. There is no box in the box in the box happening like with recursion.

I don't really want to have to add properties (or instance variables) to the TreeNode object as this should be re-usable in a generic way for any kind of object graph.

Does anyone have an idea how to do this? Must I introduce another array to keep track of visited nodes?


回答1:


I think you do need to stack the depths as well. This is what you would actually have done anyway, if you had a recursive version. It's just that the storage would be “invisible”, since you would have used the call stack instead of an explicit stack like you are doing now.

If it helps you, you could easily convert the depth-first search to a breadth-first search, by using the array as a queue instead of a stack. (Just do removeFirstObject instead of removeLastObject.) Then you would know that you always look at the nodes in order of non-decreasing depth. However, if you need exact depths, I think you still need to add some storage for keeping track of when you have to increment the current depth.

Update:

You should be able to do a DFS without the stack altogether, if instead you follow parent pointers of the node to back up the tree. That would make maintaining the depth simple. But you would have to be careful not to break linear-time worst-case complexity by rescanning children to find out where you were.

If you don't have parent pointers, it should be possible to stack just enough information to keep track of the parents. But this would mean that you put some more information on the stack than you are currently doing, so it would not be much of an improvement over stacking the depths directly.

By the way, looking carefully on your algorithm, aren't you looking at the wrong side of the array when you get the next current node? It should work like this:

push root
while stack not empty:
   current = pop
   push all children of current



回答2:


Im not understanding your notation, but if I read correctly you process a node and add all children to your list of work to do.

If you could change that part to using a recursion, you could track the tree-depth since it would be the recursion depth.

So instead of adding the child node, recurse for each child node.

hth

Mario




回答3:


I believe what you are doing actually is BFS. You are working with lists. For doing DFS, you should use a stack;

This might be useful for the depth track, you might look into the vector p (of parents)




回答4:


Supposing you are doing BFS, the easiest thing to do is to introduce another queue for depth that mirrors your nodes queue. Initialize the depth to zero. Each time you push to the node queue, push the current depth + 1 to the depth queue.



来源:https://stackoverflow.com/questions/5788299/how-to-track-the-depth-in-this-object-graph-depth-first-search-algorithm

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!