Assuming that the ID of the parent node (the one closer to the root) is always greater than the ID of the child node, as it seems to be the case in your examples, you can easily see from any edge whether it leads towards the root or away from it. Thus the basic algorithms would be:
given nodes n and m
find edge (x, n) or (n, x) such that x < n
repeat with node x until x is m or x is root
I don't think there is a faster way to find out whether one node is 'between' root and the other. You can, of course, improve performance by using appropriate data structures, e.g by first mapping each node to its parent in a hash set. Here's an example in Python:
ROOT = 1
edges = ((1, 2), (2, 4), (2, 5), (1, 3), (3, 6), (3, 7), (3, 8))
parents = {}
for edge in edges:
parent, child = min(edge), max(edge)
parents[child] = parent
def is_anchestor_of(p, c):
while c > p:
if parents[c] == p:
return True
c = parents[c]
return False
Complexity in both, time and space, for creating the hash map is O(n) in the number of nodes or edges (which is pretty much the same in a tree), and average case complexity for is_anchestor_of
is O(logn), but can deteriorate to O(n) in the worst case (extremely unbalanced tree, or chain).
You can improve the lookup complexity by mapping each node to all of it's anchestors. Complexity for creating this hash map would be O(n log n), unless I'm mistaken, both time and space, but could probably go up to O(n^2) in the worst case. In any case, using this structure, the complexity of is_anchestor_of
is O(1), since it is just a lookup in a hash map followed by a lookup in a hash set.
anchestors = {}
for node in parents:
anchestors[node] = set([ ROOT ])
p = parents[node]
while p != ROOT:
anchestors[node].add(p)
p = parents[p]
def is_anchestor_of(p, c):
return p in anchestors[c]
In both cases, just check whether one is an anchestor of the other.
def on_one_path(x, y):
return is_anchestor_of(x, y) if x < y else is_anchestor_of(y, x)
print on_one_path(3, 8)
Update: Seems there is a more efficient approach; see @Loha's answer.