Search code examples
pythonalgorithmbinary-treebinary-search-treebinary-search

Deleting a binary tree node in Python. Why self != parent.left or parent.right?


I have two really similar programs which have the same purpose (remove a node as a binary tree method in a class). Only one of them work. I would love if you tell me why.

The functional program, it ends with:

elif parent.left == self:
     parent.left = self.left if self.left is not None else self.right
            
elif parent.right == self:
     parent.right = self.left if self.left is not None else self.right

But there's the other program which doesn't work and ends with:

elif parent.left == self:
     self = self.left if self.left is not None else self.right
                
elif parent.right == self:
     self = self.left if self.left is not None else self.right 

So why self != parent.left or parent.right?

These are the two complete methods:

#It works
def remove(self, value, parent=None):
    if value < self.value:
        if self.left is not None:
            self.left.remove(value, self)
            
    elif value > self.value:
        if self.right is not None:
            self.right.remove(value, self)
            
    else:                                                    
        if self.left is not None and self.right is not None: 
            self.value = self.right.getMinValue()
            self.right.remove(self.value, self)
            
        elif parent is None:
            if self.left is not None:
                self.value = self.left.value
                self.right = self.left.right
                self.left = self.left.left
            elif self.right is not None:
                self.value = self.right.value
                self.left = self.right.left
                self.right = self.right.right
            else:
                pass
            
        elif parent.left == self:
            parent.left = self.left if self.left is not None else self.right
            
        elif parent.right == self:
            parent.right = self.left if self.left is not None else self.right
#It does not
def remove(self, value, parent=None):
        if value < self.value:
            if self.left is not None:
                self.left.remove(value, self)
                
        elif value > self.value:
            if self.right is not None:
                self.right.remove(value, self)
        
        else:
            if self.left is not None and self.right is not None:
                self.value = self.right.getMinValue()
                self.right.remove(self.value, self)
                
            elif parent is None:
                if self.left is not None:
                    self.value = self.left.value
                    self.right = self.left.right
                    self.left = self.left.left
                elif self.right is not None:
                    self.value = self.right.value
                    self.left = self.right.left
                    self.right = self.right.right
                else:
                    pass
            
            elif parent.left == self:
                self = self.left if self.left is not None else self.right
                
            elif parent.right == self:
                self = self.left if self.left is not None else self.right 

Solution

  • The reason the second snippet fails is that it doesn't change what parent.left or parent.right refer to.

    The remove() method is all about changing the tree structure so you want to change what parent.left or parent.right refer to. Changing what self refers to changes nothing in the tree.

    Mandatory link to Ned Batchelder