简体   繁体   English

Python中的二叉搜索树删除函数

[英]Binary search tree deletion function in Python

I'm beginner in Python and I tried to create a function to delete a node in a binary search tree.我是 Python 初学者,我尝试创建一个函数来删除二叉搜索树中的节点。

I tried calling .delete on a node.我尝试在节点上调用.delete The node is a leaf node with no children so it should be deleted.该节点是没有子节点的叶节点,因此应将其删除。 However, after I called .delete , the node is still there.但是,在我调用.delete ,该节点仍然存在。

This is the code:这是代码:

class Node:
    def __init__(self,key): 
        self.left = None
        self.right = None
        self.val = key 

    #some functions for insert etc.

    def delete(self, key):
        """DELETE"""
        try:
            if self is None:
                print("Tree is empty.")
                return None
            else:
                if key < self.val: 
                    self.left.delete(key) 

                elif key > self.val: 
                    self.right.delete(key)

                else: 
                    #this seems to be the problem
                    if self.left is None : 
                        temp = self.right
                        #print(self, self.val, self.right)
                        self = temp
                        return

                    elif self.right is None : 
                        temp = self.left  
                        self = temp
                        return  

                    temp = minValue(self.right)  
                    self.val = temp.val 

                    self.right.delete(temp.val) 
        except(AttributeError):
            print("There's no such number in a tree.")


def inorder(root):
    if root is not None: 
        inorder(root.left) 
        print(root.val, end=" ") 
        inorder(root.right) 


def minValue(node): 
    current = node  
    while(current.left is not None): 
        current = current.left    
    return current

r = Node(50)

After inserting numbers 30 20 40 70 60 80 to r and calling inorder(r) I get: 20 30 40 50 60 70 80 , which corresponds to the tree将数字30 20 40 70 60 80插入到r并调用inorder(r)我得到: 20 30 40 50 60 70 80 ,它对应于树

      50 
    /    \ 
   30     70 
  /  \   /  \ 
 20  40 60  80 

but after r.delete(30) , I get: 20 40 40 50 60 70 80 , which is:但在r.delete(30) ,我得到: 20 40 40 50 60 70 80 ,即:

      50 
    /    \ 
   40     70 
  /  \   /  \ 
 20  40 60  80 

The value to delete is replaced correctly but the used node ( 40 ) without children should be deleted.要删除的值已正确替换,但应删除没有子节点的已使用节点 ( 40 )。

What may be the reason of such a problem?出现这种问题的原因可能是什么?

Simply put, you cannot assign anything to self .简而言之,您不能为self分配任何内容。 In Python, self is a reference to the object that you called the method on.在 Python 中, self是对调用方法的对象的引用。 It would not be None (so you don't need the if self is None check), and you cannot assign some other value to it.它不会是None (因此您不需要if self is None检查),并且您不能为其分配其他值。

However, when deleting a node from the tree, it is possible that the current node (the node which you called delete on) will be deleted.但是,从树中删除节点时,可能会删除当前节点(您调用delete的节点)。 Instead of assigning values to self , we can make the delete return a node object.我们可以让delete返回一个节点对象,而不是给self赋值。 If the current node is not deleted, simply return itself;如果当前节点没有被删除,直接返回自身; otherwise, return the node the will take its place (or None if the entire subtree is gone).否则,返回将取代其位置的节点(如果整个子树都消失了,则返回None )。

Here's the modified implementation, along with an insert method and a test case:这是修改后的实现,以及一个insert方法和一个测试用例:

class Node:
    def __init__(self, key):
        self.left = self.right = None
        self.val = key

    def delete(self, key):
        """Delete a node with value `key`."""
        if key < self.val: 
            # Find and delete the value in the left subtree.
            if self.left is None:
                # There's no left subtree; the value does not exist.
                raise ValueError("Value not found in tree")
            self.left = self.left.delete(key)
            return self  # current node not deleted, just return
        elif key > self.val: 
            # Find and delete the value in the right subtree.
            if self.right is None:
                # There's no right subtree; the value does not exist.
                raise ValueError("Value not found in tree")
            self.right = self.right.delete(key)
            return self  # current node not deleted, just return
        else:
            # The current node should be deleted.
            if self.left is None and self.right is None:
                # The node has no children -- it is a leaf node. Just delete.
                return None

            # If the node has only one children, simply return that child.
            if self.left is None:
                return self.right
            if self.right is None:
                return self.left

            # The node has both left and right subtrees, and they should be merged.
            # Following your implementation, we find the rightmost node in the
            # left subtree and replace the current node with it.
            parent, node = self, self.left
            while node.right is not None:
                parent, node = node, node.right
            # Now, `node` is the rightmost node in the left subtree, and
            # `parent` its parent node. Instead of replacing `self`, we change
            # its attributes to match the value of `node`.
            if parent.left is node:
                # This check is necessary, because if the left subtree has only
                # node, `node` would be `self.left`.
                parent.left = None
            else:
                parent.right = None
            self.val = node.val
            return self

    def insert(self, key):
        if key < self.val:
            if self.left is None:
                self.left = Node(key)
            else:
                self.left.insert(key)
        else:
            if self.right is None:
                self.right = Node(key)
            else:
                self.right.insert(key)

def inorder_traverse(node):
    if node is None:
        return []
    ret = []
    if node.left is not None:
        ret += inorder_traverse(node.left)
    ret.append(node.val)
    if node.right is not None:
        ret += inorder_traverse(node.right)
    return ret

values = [5, 1, 2, 7, 3, 6, 4]
root = Node(values[0])
for x in values[1:]:
    root.insert(x)
print(inorder_traverse(root))

for x in values:
    root = root.delete(x)
    print(inorder_traverse(root))

The output is, as expected:正如预期的那样,输出是:

[1, 2, 3, 4, 5, 6, 7]
[1, 2, 3, 4, 6, 7]
[2, 3, 4, 6, 7]
[3, 4, 6, 7]
[3, 4, 6]
[4, 6]
[4]
[]

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM