Search code examples
binary-treebinary-search-tree

Binary tree deletion with minimum function


so basicly I have a class for binary tree and I really want to make deletion function but I keep messing something up.

So here is what's working:

class node(object):
    def __init__(self, number=None, par=None):
        self.number=number
        self.left=None
        self.right=None
        self.parent=par

class tree(object):
    def __init__(self):
        self.dummy=node()
    def Add(self, num, nd=None):
        if(nd==None):
            nd=self.dummy.right
        if(nd==None):# jeśli drzewo było puste
            self.dummy.right=node(num, par=self.dummy)
            return
        if(nd.number>num):
            if(nd.left==None):
                nd.left=node(num, par=nd)
                return
            else:
                self.Add( num, nd.left)
                return
        else:
            if(nd.right==None):
                nd.right=node(num, par=nd)
                return
            else:
                self.Add( num, nd.right)

    def Find(self, num_to_search, _node="nic"):
        if(_node=="nic"):
            _node=self.dummy.right
        if(_node==None):
            return None
        if(_node.number==num_to_search):
            return _node
        if(_node.number>num_to_search):
            return self.Find(num_to_search, _node.left)
        return self.Find(num_to_search, _node.right)

    def PrintID(self, _node="nic"):
        if _node=="nic":
            _node=self.dummy.right
        if _node==None:
            return
        self.PrintID(_node.left)
        print(_node.number, end=",")
        self.PrintID(_node.right)

    def KeysSum(self, _node="nic"): #suma kluczy
        if _node=="nic":
            _node=self.dummy.right
        if _node==None:
            return 0
        return self.KeysSum(_node.left)+self.KeysSum(_node.right)+_node.number
        
    def Height(self, _node="nic"): #wysokość 
        if _node=="nic":
            _node=self.dummy.right
        if _node==None:
            return 0
        right=self.Height(_node.right)+1
        left=self.Height(_node.left)+1
        if right>left:
            return right
        else:
            return left

    def Myk(self, _node="nic", depth=0): #rysuje drzewo
        if _node=="nic":
            _node=self.dummy.right
        if _node==None:
            return
        self.Myk(_node.right, depth+1)
        for i in range(depth):
            print("  ",end="")
        print(_node.number)
        self.Myk(_node.left, depth+1)
        
    def Minimum(self, _node="nic"): #zwraca węzeł o najmniejszym kluczu
        if _node=="nic":
            _node=self.dummy.right
        if _node==None:
            return
        else:   
            while _node.left != None:
                _node=_node.left
            return _node

    def Nastepnik(self, _node="nic"):
        if _node==None:
            return None
        if _node.right!=None:
            return self.Minimum(_node.right)
        par=_node.parent
        while par!=None and _node==par.right:
            _node=par
            par=_node.parent
        return par

And now I want to use Minimum to do delete function. I did that:

def Del(self, _node):
        if _node==None:
            return
        if _node.right==None and _node.left==None:
            if _node==par.right:
                par.right=None
            if _node==par.left:
                par.left=None
            return
        if _node.right!=None and _node.left==None:
            if _node==par.right:
                par.right=_node.right
                _node.right.parent=par
            if _node==par.left:
                par.left=_node.left
                _node.right.parent=par
            return
        if _node.right==None and _node.left!=None:
            if _node==par.right:
                par.right=_node.left
                _node.left.parent=par
            if _node==par.left:
                par.left=_node.right
                _node.left.parent=par
            return
        if _node.right!=None and _node.left!=None:
            if _node==par.right:
                par.right=_node.right
                _node.right.parent=par
                self.Minimum(par)=_node.left
                _node.left.parent=self.Minimum(par)
            if _node==par.left:
                par.left=_node.left
                _node.left.parent=par
                self.Minimum(par)=_node.left
                _node.left.parent=self.Minimum(par)
            return

but it's not working. Any ideas how to fix that? I figured it's a problem with how I try to use Minimum function but honestly I have no idea how to do it differently. I also really struggle with classes so you need to forgive me for being such a moron...


Solution

  • There are several issues in your Del method:

    • par is not defined.
    • self.Minimum(par)=_node.left is not a valid assignment (syntax error).
    • The assignment par.left=_node.left is wrong when actually _node.right is the one that is not None. It should be par.left=_node.right. And a similar mixup occurs in the next if block
    • The case where self.Minimum is called is not attempting to do the job in the advised way. Besides the syntax error, there are double calls of self.Minimum which are not guaranteed the same result when you have just attempted to change the tree. Instead, you should just transfer the value of the minimum node to the node to be deleted, and then delete that minimum node instead.

    Here is your code with minimal corrections:

        def Del(self, _node):
            if _node==None:
                return
            par = _node.parent  # added
            if _node.right==None and _node.left==None:
                if _node==par.right:
                    par.right=None
                if _node==par.left:
                    par.left=None
                return
            if _node.right!=None and _node.left==None:
                if _node==par.right:
                    par.right=_node.right
                    _node.right.parent=par
                if _node==par.left:
                    par.left=_node.right  # corrected
                    _node.right.parent=par
                return
            if _node.right==None and _node.left!=None:
                if _node==par.right:
                    par.right=_node.left
                    _node.left.parent=par
                if _node==par.left:
                    par.left=_node.left  # corrected
                    _node.left.parent=par
                return
            # complete rewrite:
            minimum = self.Minimum(_node.right)
            _node.number = minimum.number
            self.Del(minimum)
    

    Some other remarks:

    • There should be no need to have a dummy node.
    • There should be no need to have parent references
    • Method names are commonly written in either camelCase or snake_case, not in PascalCase.
    • Avoid the use of the "nic" default value hack
    • Don't write an if condition when that condition can only be True (as it is the only case that ever gets to execute that if).