Queries to find distance between two nodes of a Binary tree | Python3 program to find distance between two nodes for multiple queries ; A tree node structure ; Array to store level of each node ; Utility Function to store level of all nodes ; queue to hold tree node with level ; let root node be at level 0 ; Do level Order Traversal of tree ; Node p . first is on level p . second ; If left child exits , put it in queue with current_level + 1 ; If right child exists , put it in queue with current_level + 1 ; Stores Euler Tour ; index in Euler array ; Find Euler Tour ; store current node 's data ; If left node exists ; traverse left subtree ; store parent node 's data ; If right node exists ; traverse right subtree ; store parent node 's data ; checks for visited nodes ; Stores level of Euler Tour ; Stores indices of the first occurrence of nodes in Euler tour ; Preprocessing Euler Tour for finding LCA ; If node is not visited before ; Add to first occurrence ; Mark it visited ; Stores values and positions ; Utility function to find minimum of pair type values ; Utility function to build segment tree ; Utility function to find LCA ; Function to return distance between two nodes n1 and n2 ; Maintain original Values ; Get First Occurrence of n1 ; Get First Occurrence of n2 ; Swap if low > high ; Get position of minimum value ; Extract value out of Euler tour ; return calculated distance ; Build Tree ; Store Levels ; Find L and H array ; Build sparse table ; Driver Code ; Number of nodes ; Constructing tree given in the above figure ; Function to do all preprocessing
from collections import deque NEW_LINE from sys import maxsize as INT_MAX NEW_LINE MAX = 100001 NEW_LINE class Node : NEW_LINE INDENT def __init__ ( self , data ) : NEW_LINE INDENT self . data = data NEW_LINE self . left = None NEW_LINE self . right = None NEW_LINE DEDENT DEDENT level = [ 0 ] * MAX NEW_LINE def findLevels ( root : Node ) : NEW_LINE INDENT global level NEW_LINE if root is None : NEW_LINE INDENT return NEW_LINE DEDENT q = deque ( ) NEW_LINE q . append ( ( root , 0 ) ) NEW_LINE while q : NEW_LINE INDENT p = q [ 0 ] NEW_LINE q . popleft ( ) NEW_LINE level [ p [ 0 ] . data ] = p [ 1 ] NEW_LINE if p [ 0 ] . left : NEW_LINE INDENT q . append ( ( p [ 0 ] . left , p [ 1 ] + 1 ) ) NEW_LINE DEDENT if p [ 0 ] . right : NEW_LINE INDENT q . append ( ( p [ 0 ] . right , p [ 1 ] + 1 ) ) NEW_LINE DEDENT DEDENT DEDENT Euler = [ 0 ] * MAX NEW_LINE idx = 0 NEW_LINE def eulerTree ( root : Node ) : NEW_LINE INDENT global Euler , idx NEW_LINE idx += 1 NEW_LINE Euler [ idx ] = root . data NEW_LINE if root . left : NEW_LINE INDENT eulerTree ( root . left ) NEW_LINE idx += 1 NEW_LINE Euler [ idx ] = root . data NEW_LINE DEDENT if root . right : NEW_LINE INDENT eulerTree ( root . right ) NEW_LINE idx += 1 NEW_LINE Euler [ idx ] = root . data NEW_LINE DEDENT DEDENT vis = [ 0 ] * MAX NEW_LINE L = [ 0 ] * MAX NEW_LINE H = [ 0 ] * MAX NEW_LINE def preprocessEuler ( size : int ) : NEW_LINE INDENT global L , H , vis NEW_LINE for i in range ( 1 , size + 1 ) : NEW_LINE INDENT L [ i ] = level [ Euler [ i ] ] NEW_LINE if vis [ Euler [ i ] ] == 0 : NEW_LINE INDENT H [ Euler [ i ] ] = i NEW_LINE vis [ Euler [ i ] ] = 1 NEW_LINE DEDENT DEDENT DEDENT seg = [ 0 ] * ( 4 * MAX ) NEW_LINE for i in range ( 4 * MAX ) : NEW_LINE INDENT seg [ i ] = [ 0 , 0 ] NEW_LINE DEDENT def minPair ( a : list , b : list ) -> list : NEW_LINE INDENT if a [ 0 ] <= b [ 0 ] : NEW_LINE INDENT return a NEW_LINE DEDENT else : NEW_LINE INDENT return b NEW_LINE DEDENT DEDENT def buildSegTree ( low : int , high : int , pos : int ) -> list : NEW_LINE INDENT if low == high : NEW_LINE INDENT seg [ pos ] [ 0 ] = L [ low ] NEW_LINE seg [ pos ] [ 1 ] = low NEW_LINE return seg [ pos ] NEW_LINE DEDENT mid = low + ( high - low ) // 2 NEW_LINE buildSegTree ( low , mid , 2 * pos ) NEW_LINE buildSegTree ( mid + 1 , high , 2 * pos + 1 ) NEW_LINE seg [ pos ] = min ( seg [ 2 * pos ] , seg [ 2 * pos + 1 ] ) NEW_LINE DEDENT def LCA ( qlow : int , qhigh : int , low : int , high : int , pos : int ) -> list : NEW_LINE INDENT if qlow <= low and qhigh >= high : NEW_LINE INDENT return seg [ pos ] NEW_LINE DEDENT if qlow > high or qhigh < low : NEW_LINE INDENT return [ INT_MAX , 0 ] NEW_LINE DEDENT mid = low + ( high - low ) // 2 NEW_LINE return minPair ( LCA ( qlow , qhigh , low , mid , 2 * pos ) , LCA ( qlow , qhigh , mid + 1 , high , 2 * pos + 1 ) ) NEW_LINE DEDENT def findDistance ( n1 : int , n2 : int , size : int ) -> int : NEW_LINE INDENT prevn1 = n1 NEW_LINE prevn2 = n2 NEW_LINE n1 = H [ n1 ] NEW_LINE n2 = H [ n2 ] NEW_LINE if n2 < n1 : NEW_LINE INDENT n1 , n2 = n2 , n1 NEW_LINE DEDENT lca = LCA ( n1 , n2 , 1 , size , 1 ) [ 1 ] NEW_LINE lca = Euler [ lca ] NEW_LINE return level [ prevn1 ] + level [ prevn2 ] - 2 * level [ lca ] NEW_LINE DEDENT def preProcessing ( root : Node , N : int ) : NEW_LINE INDENT eulerTree ( root ) NEW_LINE findLevels ( root ) NEW_LINE preprocessEuler ( 2 * N - 1 ) NEW_LINE buildSegTree ( 1 , 2 * N - 1 , 1 ) NEW_LINE DEDENT if __name__ == " _ _ main _ _ " : NEW_LINE INDENT N = 8 NEW_LINE root = Node ( 1 ) NEW_LINE root . left = Node ( 2 ) NEW_LINE root . right = Node ( 3 ) NEW_LINE root . left . left = Node ( 4 ) NEW_LINE root . left . right = Node ( 5 ) NEW_LINE root . right . left = Node ( 6 ) NEW_LINE root . right . right = Node ( 7 ) NEW_LINE root . right . left . right = Node ( 8 ) NEW_LINE preProcessing ( root , N ) NEW_LINE print ( " Dist ( 4 , ▁ 5 ) ▁ = " , findDistance ( 4 , 5 , 2 * N - 1 ) ) NEW_LINE print ( " Dist ( 4 , ▁ 6 ) ▁ = " , findDistance ( 4 , 6 , 2 * N - 1 ) ) NEW_LINE print ( " Dist ( 3 , ▁ 4 ) ▁ = " , findDistance ( 3 , 4 , 2 * N - 1 ) ) NEW_LINE print ( " Dist ( 2 , ▁ 4 ) ▁ = " , findDistance ( 2 , 4 , 2 * N - 1 ) ) NEW_LINE print ( " Dist ( 8 , ▁ 5 ) ▁ = " , findDistance ( 8 , 5 , 2 * N - 1 ) ) NEW_LINE DEDENT