简体   繁体   中英

Find depth of node in tree

I am trying to write a function that returns the depth of a node in a non binary tree. I've been trying for the past few hours and getting nowhere so any help would be appreciated. I keep getting 1 as a result. I am searching the tree for the exact same instances of Person.

/** 
 * Return the depth at which p occurs in this BugTree, 
 * or -1 if p is not in the BugTree.
 * Note: depth(root) is 0.
 * If p is a child of this BugTree, then depth(p) is 1. etc.
*/
public int depth(Person p) {
    if (root == p) return 0;
    if (childrenSize() == 0) return 0;
    int d= 0;
    for (BugTree c : children) {
        if (c.getRoot() == p) return 1;
        int k= c.depth(p);
        if (k != 1) {
            d= 1 + c.depth(p);
        } else {
            return d;
        }
    }

    return d;
}

Do Level Order Traversal starting from Root node. Let the Node have a property called depth. In Level order traversal, when you add children, have their depths as parent's depth + 1. Level Order Traversal uses a Queue data structure and is pretty simple.

        1       Level 1 or 0
      2   3     Level 2 or 1
    4  5 6  7   Level 3 or 2

Level Order Traversal: 1 2 3 4 5 6 7

Algorithm:

LevelOrder(tree)

1) Create an empty queue q

2) temp_node = root; //with depth = 0    *start from root

3) Loop while temp_node is not NULL

    a) is temp_node the node needed? if yes print it's depth.

    b) Enqueue temp_node’s children (first left then right children) to q with child's depth = temp_node’s depth + 1

    c) Dequeue a node from q and assign it’s value to temp_node

Checkout Level Order Traversal: https://gist.github.com/yitonghe00/0b3ba3d3ad8dc008c1ebf30d0a9e8773V

Using the name root for the data payload of a node is misleading. A sorted tree could compare, and pick the right subtree - much faster.

public int depth(Person p) {
    if (data == p) { // data.equals(p)
        return 0;
    }
    for (BugTree c : children) {
        int d = c.depth(p);
        if (d != -1) {
            return 1 + d;
        }
    }
    return -1;
}

As you see it is much simpler.

I would recommend you return an Optional<Integer> rather than using an int with a special value that means 'not found'. That is (IMO) clearer and less error prone. Using Java streams the solution would look like:

public Optional<Integer> depth(Person person) {
    if (data.equals(person))
        return Optional.of(1);
    else
        return children.stream()
            .flatMap(ch -> ch.depth(person).stream())
            .findAny().map(d -> d + 1);
}

Note: I have used Optional<Integer> rather than OptionalInt to use the map method. It'd certainly be possible to use OptionalInt as well but the code would be slightly more complicated. If someone knows why the type specific variants don't have filter and map methods I'd love to hear it!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM