删除BST中的节点(python)

时间:2018-04-23 17:47:31

标签: python binary-search-tree

尝试在python中构建二进制搜索树,并遇到了这个奇怪的错误。使用我的delete_node函数删除节点后,仍然会打印已删除的节点,但只有正确删除的节点是连接了两个其他节点的节点(这些节点应该是最难删除的) 这是代码:

class Node:
  def __init__(self, data):
    self.Left = self.Right = None
    self.T_data = data


# function that deletes nodes from the tree
  def delete_node(self, item):
    if self is None:
      return self
    elif item < self.T_data:
      self.Left.delete_node(item)
    elif item > self.T_data:
      self.Right.delete_node(item)
    else:
      # case when the node we want to delete has no leaves attached to it
      if self.Right is None and self.Left is None:
        self = None
      # cases when a node has either left or right leaf node
      elif self.Left is None:
        temp = self.Right
        self = None
        return temp
      elif self.Right is None:
        temp = self.Left
        self = None
        return temp
      else: #case when a node has two leaf nodes attached
        temp = self.Right.min_node()
        self.T_data = temp.T_data
        self.Right = self.Right.delete_node(temp.T_data)
    return self

正如您所看到的,删除节点的方式是使用递归,因此要使双分支节点删除,单分支节点删除应该正常工作,但事实并非如此。

继承了打印功能以及如何调用函数:

# function that prints contents of the tree in preorder fashion
  def print_tree_preorder(self):
    if self is None:
      return
    print("%s" % self.T_data)
    if self.Left is not None:
      self.Left.print_tree_preorder()
    if self.Right is not None:
      self.Right.print_tree_preorder()

x = int(input("Which element would you like to delete?\n"))
  root = root.delete_node(x)
  root.print_tree_preorder()

1 个答案:

答案 0 :(得分:0)

你现在在做什么,当你有:

self = None

实际上是删除对象本身。您正在做的是将self分配给不同的值。

我认为说明这个问题的好方法是将self和其他变量视为标记

当你说:

a = 3

你基本上把标记a放在实体3上.3驻留在内存中的某个地方,a“指向”3(尽管C ++中的指针实际上不是python中的引用,如果要进行比较,请小心。

当您将self指向None时,您想要的内容是:

  

所以我想删除这个对象,指向此对象的所有内容都将指向None

但是,您现在所说的是:

  

所以我想将self标记设置为指向None

哪个完全不同。仅仅因为您将self代码设置为None并不意味着您也将节点的父级.Right.Left成员设置为None

解决方案?嗯,你不会喜欢这个,但是你必须要么:

  1. 指向每个节点的父节点,并将父节点的子节点(具体为此子节点)设置为None

  2. 检查树中更深层的1个级别,这样就可以删除子节点而不是删除节点本身。

  3. 2节点子节点的工作原理是因为您在此处设置了对象的属性,而不是设置self=None。这意味着你仍然指向同一个对象,特别是在这一行:

    self.T_data = temp.T_data
    

    这是之间的区别“着色一个对象不会使它成为一个不同的对象。它的特征只是不同”“用另一个对象替换一个对象使它成为一个不同的对象”