I have not often written recursive functions/methods. I successfully understand the "base case" in simpler functions such as the following:
def countdown(num):
if num == 0: # Base case
return
print(num) # Action
countdown(num-1) # Reduction and recurse
def factorial(num):
if num == 0 or num == 1: # Base cases
return 1
return factorial(num-1) * num # reduction + recurse + action
However, I have programmed an algorithm that finds the closest value to a given value in a Binary Search Tree (BST), as well as insertion, print all nodes, and other such algorithms. I've found these algorithms to be much harder to understand especially with regard to identify the base cases. This question specifically pertains to the following implementation of findClosest and _findClosest. Consider:
class BSTNode:
def __init__(self,value=None):
self.value = value
self.leftChild = None
self.rightChild = None
class BST:
def __init__(self):
self.root = None
def findClosest(self, value):
if self.root is None: # Base case 0
print("There is no tree, so can't find closest!")
return None
else:
return self._findClosest(value, self.root, self.root.value)
def _findClosest(self, searchValue, currentNode, closest):
if currentNode is None: # Base case #1
return closest
if abs(currentNode.value - closest) < abs(closest - searchValue): # ACTION
closest = currentNode.value
if searchValue > currentNode.value: # Reduce and recurse
return self._findClosest(searchValue,currentNode.rightChild, closest)
elif searchValue < currentNode.value: # Reduce and recurse
return self._findClosest(searchValue,currentNode.leftChild,closest)
else:
return currentNode.value # Base case #2
You can see that I attempted to identify the base cases. As I am using a sort of "driver, pseudo-public" method which handles the first base case of no root separately, I labeled that "base case 0". In any event, my point of confusion is that there are 4 separate return statements in _findClosest(), and my current knowledge of recusion would have me surmising that the two I've labeled Base case #1 and Base case #2 with comments are in fact the only two base cases in that method. However, in order for this method to work correctly, I've also had to return the results of _findClosest() when called on the leftChild and rightChild, so would these also be more base cases? I am having a difficult time determining what is a base case vs. what is the reduction/recursive step. The fact that there are multiple base cases and separate "paths of recursion" if you will, is far more difficult for me to understand than those simple recursive functions that I mentioned earlier. Finally, the base cases in the _findClosest method are also spread out, with the recursive calls sandwiched in the middle, further adding to my confusion.
Please note that the code provided runs fine on Python 3.7.9, however I purposely did not include the rest of the BST methods and driver as I was concerned with including too much code. I also am not sure that this questions would require those remaining items. If a suitable answer does, I will edit and add them.