@@ -415,6 +415,143 @@ def rank(self, x):
415
415
walk = p
416
416
return r
417
417
418
+ def _simple_path (self , key , root ):
419
+ """
420
+ Utility funtion to find the simple path between root and node.
421
+
422
+ Parameter
423
+ =========
424
+
425
+ key: Node.key
426
+ Key of the node to be searched
427
+
428
+ Returns
429
+ =======
430
+
431
+ path: list
432
+ """
433
+
434
+ stack = Stack ()
435
+ stack .push (root )
436
+ path = []
437
+ node_idx = - 1
438
+
439
+ while not stack .is_empty :
440
+ node = stack .pop ()
441
+ if self .tree [node ].key == key :
442
+ node_idx = node
443
+ break
444
+ if self .tree [node ].left :
445
+ stack .push (self .tree [node ].left )
446
+ if self .tree [node ].right :
447
+ stack .push (self .tree [node ].right )
448
+
449
+ if node_idx == - 1 :
450
+ return path
451
+
452
+ while node_idx != 0 :
453
+ path .append (node_idx )
454
+ node_idx = self .tree [node_idx ].parent
455
+ path .append (0 )
456
+ path .reverse ()
457
+
458
+ return path
459
+
460
+ def _lca_1 (self , j , k ):
461
+ root = self .root_idx
462
+ path1 = self ._simple_path (j , root )
463
+ path2 = self ._simple_path (k , root )
464
+ if not path1 or not path2 :
465
+ raise ValueError ("One of two path doesn't exists. See %s, %s"
466
+ % (path1 , path2 ))
467
+
468
+ n , m = len (path1 ), len (path2 )
469
+ i = j = 0
470
+ while i < n and j < m :
471
+ if path1 [i ] != path2 [j ]:
472
+ return self .tree [path1 [i - 1 ]].key
473
+ i += 1
474
+ j += 1
475
+ if path1 < path2 :
476
+ return self .tree [path1 [- 1 ]].key
477
+ return self .tree [path2 [- 1 ]].key
478
+
479
+ def _lca_2 (self , j , k ):
480
+ curr_root = self .root_idx
481
+ u , v = self .search (j ), self .search (k )
482
+ if (u is None ) or (v is None ):
483
+ raise ValueError ("One of the nodes with key %s "
484
+ "or %s doesn't exits" % (j , k ))
485
+ u_left = self .comparator (self .tree [u ].key , \
486
+ self .tree [curr_root ].key )
487
+ v_left = self .comparator (self .tree [v ].key , \
488
+ self .tree [curr_root ].key )
489
+
490
+ while not (u_left ^ v_left ):
491
+ if u_left and v_left :
492
+ curr_root = self .tree [curr_root ].left
493
+ else :
494
+ curr_root = self .tree [curr_root ].right
495
+
496
+ if curr_root == u or curr_root == v :
497
+ if curr_root is None :
498
+ return None
499
+ return self .tree [curr_root ].key
500
+
501
+ u_left = self .comparator (self .tree [u ].key , \
502
+ self .tree [curr_root ].key )
503
+ v_left = self .comparator (self .tree [v ].key , \
504
+ self .tree [curr_root ].key )
505
+
506
+ if curr_root is None :
507
+ return curr_root
508
+ return self .tree [curr_root ].key
509
+
510
+ def lowest_common_ancestor (self , j , k , algorithm = 1 ):
511
+
512
+ """
513
+ Computes the lowest common ancestor of two nodes.
514
+
515
+ Parameters
516
+ ==========
517
+
518
+ j: Node.key
519
+ Key of first node
520
+ k: Node.key
521
+ Key of second node
522
+ algorithm: int
523
+ The algorithm to be used for computing the
524
+ lowest common ancestor.
525
+ Optional, by default uses algorithm 1.
526
+
527
+ 1 -> Determines the lowest common ancestor by finding
528
+ the first intersection of the paths from v and w
529
+ to the root.
530
+
531
+ 2 -> Modifed version of the algorithm given in the
532
+ following publication,
533
+ D. Harel. A linear time algorithm for the
534
+ lowest common ancestors problem. In 21s
535
+ Annual Symposium On Foundations of
536
+ Computer Science, pages 308-319, 1980.
537
+
538
+ Returns
539
+ =======
540
+
541
+ Node.key
542
+ The key of the lowest common ancestor in the tree.
543
+ if both the nodes are present in the tree.
544
+
545
+ References
546
+ ==========
547
+
548
+ .. [1] https://en.wikipedia.org/wiki/Lowest_common_ancestor
549
+
550
+ .. [2] https://pdfs.semanticscholar.org/e75b/386cc554214aa0ebd6bd6dbdd0e490da3739.pdf
551
+
552
+ """
553
+ return getattr (self , "_lca_" + str (algorithm ))(j , k )
554
+
418
555
class AVLTree (BinarySearchTree ):
419
556
"""
420
557
Represents AVL trees.
0 commit comments