0

How would I be able to create common tree operations such as insert and search while passing in functions to reduce redundancy. For example, a recursive function calls itself on the left branch when the value passed in is greater than the current node. If I were able to pass in functions like insert and search, I'd be able to factor out a lot of the traversal. The main problem area I'm seeing is that both functions have different base cases. Example solutions in python would be appreciated.

def insert(n, node = root):
    if node == None:
        node.data = n
        node.left, node.right, node.middle = None
    elif node.data == n:
        insert(node.middle)
    elif node.data < n:
        insert(right)
    else:
        insert(left)


def search(n, node = root):
    if node == None:
        return false
    elif node.data == n:
        return true
    elif node.data < n:
        search(right)
    else:
        search(left)
ReyCharles
  • 1,772
  • 10
  • 30
Something Jones
  • 315
  • 1
  • 2
  • 7
  • Have you written any code yourself you could provide? – Totem Oct 19 '14 at 02:29
  • It would be a lot more readable if you edit your post and stick it in there with the code formatting option ;) – Totem Oct 19 '14 at 02:35
  • It won't let me edit the comment and it looks like I already did put the code formater in but it didn't take for some reason. – Something Jones Oct 19 '14 at 02:39
  • I meant that you should edit your actual Post above(your original question) and enter the code there. You can format code there so it looks good. Press the 'edit' button (in between 'share' and 'flag') – Totem Oct 19 '14 at 02:42
  • I fixed my post. Let me know if you have any ideas how I could factor those last two cases out. – Something Jones Oct 19 '14 at 02:58
  • Can you explain yourself better? what would you like to do? save code? for example use search in insert to find the place and then just add the element? – TomerZ Oct 19 '14 at 16:36
  • I'm trying to save code. If you look at the last two cases in both functions, they're identical except the function called. I'm trying to figure out a good way to create a traverse function which I can pass in functions like insert or search. Using search to find the place and then insert is definitely a case I was hoping to use. – Something Jones Oct 19 '14 at 17:52

2 Answers2

0

Your logic for inserting is not correct. You are trying to set attributes on None.

For reusing common code you can use function decorators. Implement common code for traversing tree in decorator function and action on found element in operation function. You can change your code as follow:

def tree_operation(f):
    def recursive_wrapper(n, node):
       if node == None or node.data == n:
           # tree traversed to final point. do action for found element or
           # None
           return f(n, node)
       # try getting closer to interesting element
       elif node.data < n:
           return recursive_wrapper(n, node.right)
       else:
           return recursive_wrapper(n, node.left)
    return recursive_wrapper

@tree_operation
def search(n, node):
    if node == None:
        return False
    elif node.data == n:
        return True

@tree_operation
def insert(n, node):
    if node == None:
        # this obviously fail
        node.data = n
        node.left, node.right, node.middle = None
    elif node.data == n:
        insert(node.middle)

In fact it passes functions, as you noted in question plus renames resultant function to passed in function. Above decorator syntax for insert function does this:

insert = tree_operation(insert)
reith
  • 2,028
  • 13
  • 26
0

I think its better to not combine the iterative part of functions in a single one because it complicates the code. But if you think that the iterative part is complex and you need to write it once, you can re-factor it as follow:

def do_iterate(base_function, n, node=root):
    if node == None or node.data == n:
        base_function(n, node)
    elif node.data < n:
        do_iterate(base_function, n, node.right)
    else:
        do_iterate(base_function, n, node.left)

Then, you can write your own base_function that will be called when the base conditions met. For example you can use base_insert() and base_search() functions in place of insert() and search() functions.

def base_insert(n, node):
    if node == None:
        node.data = n
        node.left, node.right, node.middle = None
    else:
        do_iterate(base_insert, n, node.middle)

def base_search(n, node):
    if node == None:
        return false
    else:
        return true

So you can use your algorithms like below:

do_iterate(base_insert, 7)
do_iterate(base_search, 4)

At the end, I'm not sure it's better than your simple code.

Aliakbar Abbasi
  • 209
  • 1
  • 10