Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to find the nearest common ancestors of two or more nodes?

Users selects two or more elements in a HTML page. What i want to accomplish is to find those elements' common ancestors (so body node would be the common ancestor if none found before) ?

P.S: It can be achieved with XPath but it is not a preferable option for me. Also it may be found with css selector parsing but i think it is a dirty method (?)

Thank you.

like image 630
Ozgur Avatar asked Oct 18 '10 15:10

Ozgur


People also ask

How do I find the nearest common ancestor?

In ontologies, the lowest common ancestor is also known as the least common ancestor. In a tree data structure where each node points to its parent, the lowest common ancestor can be easily determined by finding the first intersection of the paths from v and w to the root.

What approach will you follow to find the lowest common ancestor LCA of any two nodes in BST?

Approach: For Binary search tree, while traversing the tree from top to bottom the first node which lies in between the two numbers n1 and n2 is the LCA of the nodes, i.e. the first node n with the lowest depth which lies in between n1 and n2 (n1<=n<=n2) n1 < n2.

How do you calculate LCA?

A simple solution would be to store the path from root to x and the path from the root to y in two auxiliary arrays. Then traverse both arrays simultaneously till the values in the arrays match. The last matched value will be the LCA. If the end of one array is reached, then the last seen value is LCA.


2 Answers

Here's a pure JavaScript version that is a little more efficient.

function parents(node) {   var nodes = [node]   for (; node; node = node.parentNode) {     nodes.unshift(node)   }   return nodes }  function commonAncestor(node1, node2) {   var parents1 = parents(node1)   var parents2 = parents(node2)    if (parents1[0] != parents2[0]) throw "No common ancestor!"    for (var i = 0; i < parents1.length; i++) {     if (parents1[i] != parents2[i]) return parents1[i - 1]   } } 
like image 74
benpickles Avatar answered Sep 21 '22 06:09

benpickles


The solutions involving manually going through the ancestor elements are far more complicated than necessary. You don't need to do the loops manually. Get all the ancestor elements of one element with parents(), reduce it to the ones that contain the second element with has(), then get the first ancestor with first().

var a = $('#a'),     b = $('#b'),     closestCommonAncestor = a.parents().has(b).first(); 

jsFiddle example

like image 20
lonesomeday Avatar answered Sep 23 '22 06:09

lonesomeday