Search code examples
pythonrecursionkdtree

Returning a list of values from a tree recursion


I'm trying to teach myself about data structures, and I'm implementing a k-d tree in Python. I have a method to search for points in the tree within a certain radius of one point in my k-d tree class:

def within_radius(self, point, radius, result=[]):
    """
    Find all items in the tree within radius of point
    """
    d = self.discriminator

    if in_circle(point, radius, self.data):
        result.append(self.data)

    # Check whether any of the points in the subtrees could be
    # within the circle
    if point[d] - radius < self.data[d] and self.l_child:
        result.append(self.l_child.within_radius(point, radius, result))

    if point[d] + radius > self.data[d] and self.r_child:
        result.append(self.r_child.within_radius(point, radius, result))

    return result

It works, but the list it returns is pretty funky, with duplicate values from the recursive calls with result. What is a good way of "accumulating" the values returned from a tree recursion into a list? I've been thinking about it for a while but I can't really see how.


Solution

  • I'm not sure if this is the most clean way to do it, but whenever I do recursion like this, I often add a keyword argument which is the list that is to be returned. That way, when I modify the list, I'm always modifying to the same list:

    def recurse(max, _output=None):
        if _output is None:
            _output = []
    
        #do some work here, add to your list
        _output.append(max)
    
        if max <= 0: #Some condition where the recursion stops
            return _output
        else:        #recurse with new arguments so that we'll stop someday...
            return recurse(max-1, _output=_output)
    

    This works because when the stop condition is True, the _output list is returned and passed all the way back up the stack.

    I use an underscored variable name to indicate that it is meant to be used only within the function itself. This is a slight extension to the normal way underscore-prefixed variables are used (in classes to indicate a variable is "private"), but I think it gets the point across...

    Note that this isn't very different from what you have. However, with your version, result will persist between calls since result = [] is evaluated when the function is created, not when it is called. Also, your version is appending the return value (which is the list itself). This gets quite convoluted when you think about the list holding multiple references to itself ...