I am trying to solve GeeksforGeeks problem Inorder Successor in BST:
Given a BST, and a reference to a Node x in the BST. Find the Inorder Successor of the given node in the BST.
Solutions are discussed at GeeskforGeeks, and I looked at the second approach listed there:
Method 2 (Search from root)
Parent pointer is NOT needed in this algorithm. The Algorithm is divided into two cases on the basis of right subtree of the input node being empty or not.
I took this approach, but don't understand why my attempt doesn't work as expected. This is what I tried:
def inorder_successor(root, x):
if x.right != None :
t = x.right
while t.left != None:
t = t.left
#print(t.elem)
return t
if root.left == None or root.right:
return
if root.left == x:
return root
inorder_successor(root.left, x)
inorder_successor(root.right, x)
def inorder(root):
if root == None:
return
inorder(root.left)
print(root.elem, end = ' ')
inorder(root.right)
class BTNode:
def __init__(self, elem):
self.elem = elem
self.right = None
self.left = None
# Create input BST
n20 = BTNode(20)
n8 = BTNode(8)
n22 = BTNode(22)
n4 = BTNode(4)
n12 = BTNode(12)
n10 = BTNode(10)
n14 = BTNode(14)
n20.left = n8
n20.right = n22
n8.left = n4
n8.right = n12
n12.left = n10
n12.right = n14
print('Given Tree Inorder Traversal: ', end = ' ')
inorder(n20) #Given Tree Inorder Traversal: 4 8 10 12 14 20 22
print()
# This works:
x = n8
print(f'Inorder successor of node {x.elem}: {inorder_successor(n20, x).elem}') #Inorder successor of node 8: 10
# This doesn't work (None). Expected 8
x = n4
print(f'Inorder successor of node {x.elem}: {inorder_successor(n20, x).elem}') # Error
Here is the tree that the above code tries with:
20
/ \
8 22
/ \
4 12
/ \
10 14
Problem
My code is not giving the right output when calling inorder_successor for nodes like n10 or n4: it produces an error because the inorder_successor function returns None.
However, if I print the n20.elem in line 11 it works and prints the required node element. So I am confused that this is working, but the code gives an error ("'NoneType' object has no attribute 'elem'"). The code works for nodes like n20 though.
Where is my mistake?
The following part of your code has several issues:
The
or root.rightpart will make theifcondition true whenever theroothas a right child, which is always the case in the non-recursive call of your function, and so your function returnsNonein all cases when this part of the code executes (which is whenxhas no right child).The only time this logic returns a node is where you have
return root, and in that casexis its left child. But this assumes that if the successor ofxis not its descendant, then it must be its immediate parent of which it must be the left child. This is not generally true. The successor ofxmight be its grand(grand(grand))parent...The recursive calls serve no goal, since after having done all the work, your code does not look at what they return
The fact that this tree is a BST is not exploited in this part of your code. For instance, when
x.elemis greater thanroot.elem, it makes no sense to look inroot.leftas it is certain that the successor ofxcan only be at the right side.Correction
As you already have pointed to a resource that has provided correct code and explanation, I'll just provide here a solution that maintains the idea of using recursion.
The quoted part of your code can be replaced with this: