Binary Search Tree Flashcards

1
Q

What is a Binary Search Tree?

A

BST, like a BT, is a rooted tree, stores a key, and left and right subtree.

Properies:
each node must be greater than all keys in the left subtree and not greater that all key in the right subtree

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
2
Q

write a recursive function to insert key and construct a BST from a list.

A

we examine the root and recursively insert the new node to the left subtree if its key is less than that of the root or the right subtree if its key is greater than or equal to the root.

class Node:
    left = right = None
    # Function to create a new binary tree node having a given key
    def \_\_init\_\_(self, data):
        self.data = data
# Function to perform inorder traversal on the tree
def inorder(root):
if root is None:
    return

inorder(root.left)
print(root.data, end=' ')
inorder(root.right)
# Recursive function to insert a key into a BST
def insert(root, key):
    # if the root is None, create a new node and return it
    if root is None:
        return Node(key)
    # if the given key is less than the root node,
    # recur for the left subtree
    if key < root.data:
        root.left = insert(root.left, key)
    # otherwise, recur for the right subtree
    else:
        # key >= root.data
        root.right = insert(root.right, key)
return root
# Function to construct a BST from given keys
def constructBST(keys):
    root = None
    for key in keys:
        root = insert(root, key)
    return root

if __name__ == ‘__main__’:

keys = [15, 10, 20, 8, 12, 16, 25]

root = constructBST(keys)
inorder(root)
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
3
Q

Write an iterative function to insert the key in a binary tree and construct a binary search tree.

A

In iterative solution we keep recording of the parent node.
1) if root is none: make a node and return root

2) parent = None, cur = root
3) while root: parent = cur
of key < cur.data: cur = cur.left

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
3
Q

Write an iterative function to insert the key in a binary tree and construct a binary search tree.

A

In iterative solution we keep recording of the parent node.
1) if root is none: make a node and retur root

2) parent = None, cur = root
3) while root: parent = cur
if key < cur.data: cur = cur.left
else: cur = cur.left
4) check parent.data with key to insert the key to the left or right of key

############### code
# A class to store a BST node
class Node:
    # Function to create a new binary tree node having a given key
    def \_\_init\_\_(self, key):
        self.data = key
        self.left = self.right = None
# Function to perform inorder traversal on the tree
def inorder(root):
if root is None:
    return

inorder(root.left)
print(root.data, end=' ')
inorder(root.right)
# Iterative function to insert a key into a BST
def insertIterative(root, key):
    # start with the root node
    curr = root
    # pointer to store the parent of the current node
    parent = None
    # if the tree is empty, create a new node and set it as root
    if root is None:
        return Node(key)
    # traverse the tree and find the parent node of the given key
    while curr:
        # update the parent to the current node
        parent = curr
    # if the given key is less than the current node,
    # go to the left subtree; otherwise, go to the right subtree.
    if key < curr.data:
        curr = curr.left
    else:
        curr = curr.right
    # construct a node and assign it to the appropriate parent pointer
    if key < parent.data:
        parent.left = Node(key)
    else:
        parent.right = Node(key)
return root
# Function to construct a BST from given keys
def constructBST(keys):
    root = None
    for key in keys:
        root = insertIterative(root, key)
    return root

if __name__ == ‘__main__’:

keys = [15, 10, 20, 8, 12, 16, 25]

root = constructBST(keys)
inorder(root)
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
4
Q

Search a given key in BST, recursive

A

We begin by examining the root node. If the tree is null, the key we are searching for does not exist in the tree. Otherwise, if the key equals that of the root, the search is successful, we return the node. If the key is less than that of the root, we search the left subtree. Similarly, if the key is greater than that of the root, we search the right subtree. This process is repeated until the key is found or the remaining subtree is null. If the searched key is not found after a null subtree is reached, then the key is not present in the tree.

 On average, binary search trees with n nodes have O(log(n)) height. However, in the worst case, binary search trees can have O(n) height (for skewed trees where all the nodes except the leaf have one and only one child) when the unbalanced tree resembles a linked list.
############ code
# Recursive function to search in a given BST
def search(root, key, parent):
    # if the key is not present in the key
    if root is None:
        print('Key not found')
        return
    # if the key is found
    if root.data == key:
    if parent is None:
        print(f'The node with key {key} is root node')
    elif key < parent.data:
        print('The given key is the left node of the node with key', parent.data)
    else:
        print('The given key is the right node of the node with key', parent.data)

    return
    # if the given key is less than the root node, recur for the left subtree;
    # otherwise, recur for the right subtree
if key < root.data:
    search(root.left, key, root)
else:
    search(root.right, key, root)

if __name__ == ‘__main__’:

keys = [15, 10, 20, 8, 12, 16, 25]

root = None
for key in keys:
    root = insert(root, key)

search(root, 25, None)
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
5
Q

Search a given key in BST,iterative

A

def searchIterative(root, key):

    # start with the root node
    curr = root
    # pointer to store the parent of the current node
    parent = None
    # traverse the tree and search for the key
    while curr and curr.data != key:
        # update the parent to the current node
        parent = curr
    # if the given key is less than the current node, go to the left subtree;
    # otherwise, go to the right subtree
    if key < curr.data:
        curr = curr.left
    else:
        curr = curr.right
    # if the key is not present in the key
    if curr is None:
        print('Key not found')
        return
if parent is None:
    print(f'The node with key {key} is root node')
elif key < parent.data:
    print('The given key is the left node of the node with key', parent.data)
else:
    print('The given key is the right node of the node with key', parent.data)

if __name__ == ‘__main__’:

keys = [15, 10, 20, 8, 12, 16, 25]

root = None
for key in keys:
    root = insert(root, key)

searchIterative(root, 25)
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
6
Q

Delet a Node in a Binary serach tree, iterative

A

we need two function:

1) finding minimum from a tree, it is going to be a successor of a deleted node if deleted node has both left and right child
2) the main delting function

In writing delting function,
we have search function (parent and current), the we consider three situation:
1) Case 1: Deleting a node with no children: remove the node from the tree. parent.left =None or parent.right = Node

2) Case 2: Deleting a node with two children: call the node to be deleted N. Do not delete N. Instead, choose either its inorder successor node or its inorder predecessor node, R. Copy the value of R to N, then recursively call delete on R until reaching one of the first two cases. If we choose the inorder successor of a node, as the right subtree is not NULL (our present case is a node with 2 children), then its inorder successor is a node with the least value in its right subtree, which will have at a maximum of 1 subtree, so deleting it would fall in one of the first 2 cases.
3) Case 3: Deleting a node with one child: remove the node and replace it with its child.

################### code
# Helper function to find minimum value node in the subtree rooted at `curr`
def getMinimumKey(curr):
    while curr.left:
        curr = curr.left
    return curr
 #\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_
# Function to delete a node from a BST
def deleteNode(root, key):
    # pointer to store the parent of the current node
    parent = None
    # start with the root node
    curr = root
    # search key in the BST and set its parent pointer
    while curr and curr.data != key:
        # update the parent to the current node
        parent = curr
    # if the given key is less than the current node, go to the left subtree;
    # otherwise, go to the right subtree
    if key < curr.data:
        curr = curr.left
    else:
        curr = curr.right
    # return if the key is not found in the tree
    if curr is None:
        return root
    # Case 1: node to be deleted has no children, i.e., it is a leaf node
    if curr.left is None and curr.right is None:
    # if the node to be deleted is not a root node, then set its
    # parent left/right child to None
    if curr != root:
        if parent.left == curr:
            parent.left = None
        else:
            parent.right = None
        # if the tree has only a root node, set it to None
        else:
            root = None
    # Case 2: node to be deleted has two children
    elif curr.left and curr.right:
        # find its inorder successor node
        successor = getMinimumKey(curr.right)
        # store successor value
        val = successor.data
        # recursively delete the successor. Note that the successor
        # will have at most one child (right child)
        deleteNode(root, successor.data)
        # copy value of the successor to the current node
        curr.data = val
    # Case 3: node to be deleted has only one child
    else:
        # choose a child node
        if curr.left:
            child = curr.left
        else:
            child = curr.right
        # if the node to be deleted is not a root node, set its parent
        # to its child
        if curr != root:
            if curr == parent.left:
                parent.left = child
            else:
                parent.right = child
        # if the node to be deleted is a root node, then set the root to the child
        else:
            root = child
return root
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
7
Q

Delet a Node from BST recursively

A
Function to find the maximum value node in the subtree rooted at `ptr`
def findMaximumKey(ptr):
    while ptr.right:
        ptr = ptr.right
    return ptr
#\_\_\_\_\_\_\_\_\_\_\_\_\_\_\_
# Function to delete a node from a BST
def deleteNode(root, key):
    # base case: the key is not found in the tree
    if root is None:
        return root
    # if the given key is less than the root node, recur for the left subtree
    if key < root.data:
        root.left = deleteNode(root.left, key)
    # if the given key is more than the root node, recur for the right subtree
    elif key > root.data:
        root.right = deleteNode(root.right, key)
    # key found
    else:
        # Case 1: node to be deleted has no children (it is a leaf node)
        if root.left is None and root.right is None:
            # update root to None
            return None
        # Case 2: node to be deleted has two children
        elif root.left and root.right:
            # find its inorder predecessor node
            predecessor = findMaximumKey(root.left)
            # copy value of the predecessor to the current node
            root.data = predecessor.data
            # recursively delete the predecessor. Note that the
            # predecessor will have at most one child (left child)
            root.left = deleteNode(root.left, predecessor.data)
        # Case 3: node to be deleted has only one child
        else:
            # choose a child node
            child = root.left if root.left else root.right
            root = child
return root
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
8
Q

Construct a balanced BST from the given keys

Given an unsorted integer array that represents binary search tree (BST) keys, construct a height-balanced BST from it. For each node of a height-balanced tree, the difference between its left and right subtree height is at most 1.

A

The height of such BST in the worst-case can be as much as the total number of keys in the BST. The worst case happens when given keys are sorted in ascending or descending order, and we get a skewed tree where all the nodes except the leaf have one and only one child.

For height-balanced BSTs, with each comparison, skip about half of the tree so that each insertion operation takes time proportional to the logarithm of the total number of items n stored in the tree, i.e., log2n. This is much better than the linear time required to find items by key in an (unsorted) array or unbalanced trees.

We can easily modify the solution to get height-balanced BSTs if all keys are known in advance. The idea is to sort the given keys first. Then the root will be the middle element of the sorted array, and we recursively construct the left subtree of the root by keys less than the middle element and the right subtree of the root by keys more than the middle element.

The time complexity of the solution is O(n.log(n)), where n is the size of the BST, and requires space proportional to the tree’s height for the call stack.

code########

# A class to store a BST node
class Node:
    def \_\_init\_\_(self, data, left=None, right=None):
        self.data = data
        self.left = left
        self.right = right
# Function to perform inorder traversal on the tree
def inorder(root):
    if root is None:
        return
inorder(root.left)
print(root.data, end=' ')
inorder(root.right)
# Function to construct balanced BST from the given sorted list
def construct(keys, low, high, root):
    # base case
    if low > high:
        return root
    # find the middle element of the current range
    mid = (low + high) // 2
    # construct a new node from the middle element and assign it to the root
    root = Node(keys[mid])
    # left subtree of the root will be formed by keys less than middle element
    root.left = construct(keys, low, mid - 1, root.left)
    # right subtree of the root will be formed by keys more than the middle element
    root.right = construct(keys, mid + 1, high, root.right)
return root
# Function to construct balanced BST from the given unsorted list
def constructBST(keys):
    # sort the keys first
    keys.sort()
    # construct a balanced BST and return the root node of the tree
    return construct(keys, 0, len(keys) - 1, None)

if __name__ == ‘__main__’:

    # input keys
    keys = [15, 10, 20, 8, 12, 16, 25]
    # construct a balanced binary search tree
    root = constructBST(keys)
    # print the keys in an inorder fashion
    inorder(root)
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
9
Q

Determine whether a given binary tree is a BST or not- using recursive and greedy seacrch

A

nstead of deciding based solely on a node’s values and its children, we also need information flowing down from the parent. In the tree above, if we could remember about the node containing the value 20, we would see that the node with value 5 is violating the BST property contract.

So, the condition we need to check at each node is:

If the node is the left child of its parent, it must be smaller than (or equal to) the parent, and it must pass down the value from its parent to its right subtree to make sure none of the nodes in that subtree is greater than the parent.
If the node is the right child of its parent, it must be larger than the parent, and it must pass down the value from its parent to its left subtree to make sure none of the nodes in that subtree is lesser than the parent.

The time complexity of the above solution is O(n), where n is the size of the BST, and requires space proportional to the tree’s height for the call stack.

code

def isBST(node, minKey, maxKey):

    # base case
    if node is None:
        return True
    # if the node's value falls outside the valid range
    if node.data < minKey or node.data > maxKey:
        return False
    # recursively check left and right subtrees with an updated range
    return isBST(node.left, minKey, node.data) and \
        isBST(node.right, node.data, maxKey)
# Function to determine whether a given binary tree is a BST
def checkForBST(root):
    if isBST(root, -sys.maxsize, sys.maxsize):
        print('The tree is a BST.')
    else:
        print('The tree is not a BST')

def swap(root):

left = root.left

root. left = root.right
root. right = left
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
10
Q

Determine whether a given binary tree is a BST or not-

Using inorder subtree

A

We know that an inorder traversal of a binary search tree returns the nodes in sorted order. To determine whether a given binary tree is a BST, keep track of the last visited node while traversing the tree. Then for each encountered node in the inorder traversal, check whether the last visited node is smaller (or smaller/equal, if duplicates are to be allowed in the tree) compared to the current node.

code ##############

def isBST(root, prev):

    # base case: empty tree is a BST
    if root is None:
        return True
    # check if the left subtree is BST or not
    left = isBST(root.left, prev)
    # value of the current node should be more than that of the previous node
    if root.data <= prev.data:
        return False
    # update previous node data and check if the right subtree is BST or not
    prev.data = root.data
    return left and isBST(root.right, prev)
# Function to determine whether a given binary tree is a BST
def checkForBST(node):
    # pointer to store previously processed node in the inorder traversal
    prev = Node(-sys.maxsize)
    # check if nodes are processed in sorted order
    if isBST(node, prev):
        print('The tree is a BST!')
    else:
        print('The tree is not a BST!')
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
11
Q

Check if the given keys represent the same BSTs or not without building BST

Given two integer arrays, X and Y, representing a set of BST keys, check if they represent the same BSTs or not without building the tree. Assume that the keys are inserted into the BST in the same order as they appear in the array.

A

the time and sapve complexity is O(n2)

def isSameBST(X, Y, n):

    # if no element is present in the list, return true
    if n == 0:
        return True
    # if the first element differs in both lists (root node key), return false
    if X[0] != Y[0]:
        return False
    # if the list contains only one key, return true
    if n == 1:
        return True
# take four auxiliary spaces of size `n-1` each (as maximum keys in
# left or right subtree can be `n-1`)
leftX = [None] * (n - 1)
rightX = [None] * (n - 1)
leftY = [None] * (n - 1)
rightY = [None] * (n - 1)

k = l = m = o = 0
    # process the remaining keys and divide them into two groups
    for i in range(1, n):
        # `leftX` will contain all elements less than `X[0]`
        if X[i] < X[0]:
            leftX[k] = X[i]
            k = k + 1
        # `rightX` will contain all elements more than `X[0]`
        else:
            rightX[l] = X[i]
            l = l + 1
        # `leftY` will contain all elements less than `Y[0]`
        if Y[i] < Y[0]:
            leftY[m] = Y[i]
            m = m + 1
        # `rightY` will contain all elements more than `Y[0]`
        else:
            rightY[o] = Y[i]
            o = o + 1
    # return false if the size of `leftX` and `leftY` differs, i.e.,
    # the total number of nodes in the left subtree of both trees differs
    if k != m:
        return False
    # return false if the size of `rightX` and `rightY` differs, i.e.,
    # the total number of nodes in the right subtree of both trees differs
    if l != o:
        return False
    # check left and right subtree
    return isSameBST(leftX, leftY, k) and isSameBST(rightX, rightY, l)
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
12
Q

What is the Inorder Predecessor and Succssesor of a binary tree?

A

When you do inorder traversal of a Binary Tree, the neighbours of the given node are called predecessor and Successor.

Predecsessor: the right most element in the left subtree (findingMaximum(cur):
while cur.right:
cur = cur.right
return cur
Note: you call this function on cur.left)

Successor: The left most element in the right tree.
FindMinimum(cur):
while cur.left:
cur = cur.left
return cur
Note: you call this function on cur.right)

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
13
Q

Find inorder predecessor for the given key in a BST

Given a BST, find the inorder predecessor of a given key in it. If the key does not lie in the BST, return the previous greater node (if any) present in the BST.

A

_______________________-

Inorder predecessor of a node locates on left subtree, right most child.
if the right most child is None, we need to find the ancesstor of a node is predecessor, i.e, the node visited before the given key.
If any such node is found, then the inorder predecessor is its parent;
otherwise it does not exist

O(n)

################## code############
# Function to find the maximum value node in a given BST
def findMaximum(root):
    while root.right:
        root = root.right
    return root
# Iterative function to find inorder predecessor for a given key in a BST
def findPredecessor(root, key):
    # base case
    if not root:
        return None
prec = None

while True:
        # if the given key is less than the root node, visit the left subtree
        if key < root.data:
            root = root.left
        # if the given key is more than the root node, visit the right subtree
        elif key > root.data:
            # update predecessor to the current node before visiting
            # right subtree
            prec = root
            root = root.right
    # if a node with the desired value is found, the predecessor is the maximum
    # value node in its left subtree (if any)
    else:
        if root.left:
            prec = findMaximum(root.left)
        break
        # if the key doesn't exist in the binary tree, return previous greater node
        if root is None:
            return prec
    # return predecessor, if any
    return prec
# A class to store a BST node
class Node:
    def \_\_init\_\_(self, data, left=None, right=None):
        self.data = data
        self.left = left
        self.right = right
# Recursive function to insert a key into a BST
def insert(root, key):
    # if the root is None, create a new node and return it
    if root is None:
        return Node(key)
    # if the given key is less than the root node, recur for the left subtree
    if key < root.data:
        root.left = insert(root.left, key)
    # if the given key is more than the root node, recur for the right subtree
    else:
        root.right = insert(root.right, key)
return root

if __name__ == ‘__main__’:

keys = [15, 10, 20, 8, 12, 16, 25]
    ''' Construct the following tree
               15
             /    \
            /      \
           10       20
          / \      /  \
         /   \    /    \
        8    12  16    25
    '''
root = None
for key in keys:
    root = insert(root, key)

# find inorder predecessor for each key
for key in keys:
    prec = findPredecessor(root, key)
    if prec:
        print(f'Predecessor of node {key} is {prec.data}')
    else:
        print('The predecessor does
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
14
Q

write a function to search a key throughout a tree, return False if there is not such a node

A

def search(root, key):

traverse the tree and search for the key
while root:
# if the given key is less than the current node, go to the left
# subtree; otherwise, go to the right subtree
if root.data > key.data:
root = root.left

                        elif root.data < key.data:
                                   root = root.right
# if node is found
                         elif root.data == key.data:
                                    return True
               return False
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
15
Q

Find the Lowest Common Ancestor (LCA) of two nodes in a BST

Given a BST and two nodes x and y in it, find the lowest common ancestor (LCA) of x and y. The solution should return null if either x or y is not the actual node in the tree.

A

One way is writing path 1 and path2 which are path of root to x and y. Then traverse both paths to find the last common element
We need to write 3 functions:
1) serach functiona and return True ( if node exists ) /False (if node does not exisi)
2) Assuming x and y are in the tree LCA(root, x, y)
3) final FindLCA(root, x, y), combining 1 and 2

We can recursively find the lowest common ancestor of nodes x and y present in the BST. The trick is to find the BST node, which has one key present in its left subtree and the other key present in the right subtree. If any such node is present in the tree, then it is LCA; if y lies in the subtree rooted at node x, then x is the LCA; otherwise, if x lies in the subtree rooted at node y, then y is the LCA.

##########################

# A class to store a BST node
class Node:
    def \_\_init\_\_(self, data, left=None, right=None):
        self.data = data
        self.left = left
        self.right = right
# Recursive function to insert a key into a BST
def insert(root, key):
    # if the root is None, create a new node and return it
    if root is None:
        return Node(key)
    # if the given key is less than the root node, recur for the left subtree
    if key < root.data:
        root.left = insert(root.left, key)
    # if the given key is more than the root node, recur for the right subtree
    else:
        root.right = insert(root.right, key)
return root
# Iterative function to search a given node in a BST
def search(root, key):
    # traverse the tree and search for the key
    while root:
        # if the given key is less than the current node, go to the left
        # subtree; otherwise, go to the right subtree
        if key.data < root.data:
            root = root.left
        elif key.data > root.data:
            root = root.right
        # if the key is found, return true
        elif key == root:
            return True
        else:
            return False
    # we reach here if the key is not present in the BST
    return False
# Recursive function to find the lowest common ancestor of given nodes
# `x` and `y`, where both `x` and `y` are present in a BST
def LCARecursive(root, x, y):
    # base case: empty tree
    if root is None:
        return None
    # if both `x` and `y` is smaller than the root, LCA exists in the left subtree
    if root.data > max(x.data, y.data):
        return LCARecursive(root.left, x, y)
    # if both `x` and `y` are greater than the root, LCA exists in the right subtree
    elif root.data < min(x.data, y.data):
        return LCARecursive(root.right, x, y)
    # if one key is greater (or equal) than the root and one key is smaller
    # (or equal) than the root, then the current node is LCA
    return root
# Print lowest common ancestor of two nodes in a BST
def LCA(root, x, y):
    # return if the tree is empty, or `x` or `y` is not present in the tree
    if not root or not search(root, x) or not search(root, y):
        return
    # `lca` stores the lowest common ancestor of `x` and `y`
    lca = LCARecursive(root, x, y)
    # if the lowest common ancestor exists, print it
    if lca:
        print('LCA is', lca.data)
    else:
        print('LCA does not exist')
16
Q

Find Floor and Ceil in a Binary Search Tree- iteratively

Given a BST, find the floor and ceil of a given key in it. If the given key lies in the BST, then both floor and ceil are equal to that key; otherwise, the ceil is equal to the next greater key (if any) in the BST, and the floor is equal to the previous greater key (if any) in the BST.

A

The idea is simple – search for the given key in the tree and update the ceil to the current node before visiting its left subtree. Similarly, update the floor to the current node before visiting its right subtree. If the key is found in the BST, then the floor and ceil are equal to that key. If the key is not found in the BST, then the floor and ceil were already updated while searching for the key.

o(n), The auxiliary space required by the program is O(1).

code

def findFloorCeil(root, floor, ceil, key):

    while root:
        # if a node with the desired value is found, both floor and ceil is equal
        # to the current node
        if root.data == key:
            floor = ceil = root
            break
        # if the given key is less than the root node, visit the left subtree
        elif key < root.data:
            # update ceil to the current node before visiting the left subtree
            ceil = root
            root = root.left
        # if the given key is more than the root node, visit the right subtree
        else:
            # update floor to the current node before visiting the right subtree
            floor = root
            root = root.right
return floor, ceil
17
Q

Find inorder successor for the given key in a BST, Iteratively

Given a BST, find the inorder successor of a given key in it. If the given key does not lie in the BST, then return the next greater node (if any) present in the BST.

A

A node’s inorder successor is the node with the least value in its right subtree, i.e., its right subtree’s leftmost child. If the right subtree of the node doesn’t exist, then the inorder successor is one of its ancestors. To find which ancestors are the successor, we can move up the tree towards the root until we encounter a node that is left child of its parent. If any such node is found, then inorder successor is its parent; otherwise, inorder successor does not exist for the node.

the code is exactly like finding a predecessor.
in the recursive version, we start with searching the key.
However during the search, unlike the predecessor which we saved the root once we visit the left subtree, we save the root before moving the root to the next right subtree. This is for the cases that the node will be None
the once we found the node, we see if the node has the right subtree, if it has, we send the minimum function on the right subtree, save the ancestors and break the code.
if root is None we report the anc that we save throhjout the serach .

code

# Helper function to find minimum value node in a given BST
def findMinimum(root):
    while root.left:
        root = root.left
    return root
# Iterative function to find an inorder successor for the given key in a BST
def findSuccessor(root, key):
    # base case
    if not root:
        return None
succ = None

while True:
        # if the given key is less than the root node, visit the left subtree
        if key < root.data:
            # update successor to the current node before visiting
            # left subtree
            succ = root
            root = root.left
        # if the given key is more than the root node, visit the right subtree
        elif key > root.data:
            root = root.right
    # if a node with the desired value is found, the successor is the minimum
    # value node in its right subtree (if any)
    else:
        if root.right:
            succ = findMinimum(root.right)
        break
        # if the key doesn't exist in the binary tree, return next greater node
        if root is None:
            return succ
    # return successor, if any
    return succ
#################

if __name__ == ‘__main__’:

keys = [15, 10, 20, 8, 12, 16, 25]    root = None
for key in keys:
    root = insert(root, key)

# find inorder successor for each key
for key in keys:
    succ = findSuccessor(root, key)
    if succ:
        print(f'The successor of node {key} is {succ.data}')
    else:
        print(f'No Successor exists for node {key}') else:
18
Q

Find inorder successor for the given key in a BST, recursively

Given a BST, find the inorder successor of a given key in it. If the given key does not lie in the BST, then return the next greater node (if any) present in the BST.

A

The idea is to search for the given node in the tree and update the successor to the current node before visiting its left subtree. If the node is found in the BST, return the least value node in its right subtree, and if the right subtree of the node doesn’t exist, then inorder successor is one of the ancestors of it, which has already been updated while searching for the given key.

Summary, if root is None, return the nacestor that you have saved so far, then first check the value on the root, if it is the target, the if it has the right sub tree, find min on left side.

other wise if root.data > ket: first save the anc =root then return function with root.left
else: return function on root.right
return root

time and space O(n)
##################### code
# Recursive function to find an inorder successor for a given key in a BST
def findSuccessor(root, succ, key):
    # base case
    if root is None:
        return succ
# if a node with the desired value is found, the successor is the minimum value
# node in its right subtree (if any)
if root.data == key:
    if root.right:
        return findMinimum(root.right)
    # if the given key is less than the root node, recur for the left subtree
    elif key < root.data:
        # update successor to the current node before recursing in the left subtree
        succ = root
        return findSuccessor(root.left, succ, key)
    # if the given key is more than the root node, recur for the right subtree
    else:
        return findSuccessor(root.right, succ, key)
return succ