【问题标题】:Confusion with recursion and property setters in Python与 Python 中的递归和属性设置器混淆
【发布时间】:2015-09-30 23:39:51
【问题描述】:

我正在尝试实现一个二叉搜索树类。我有两节课; BSTNodeBST。我尝试在 leftright 的设置器中强制执行搜索树属性:

class BSTNode(object):


    def __init__(self,new):
        if type(new) is BSTNode:
            self._data = new.data
        else:
            self._data = new
        self._left = None
        self._right = None


    @property
    def data(self):
         return self._data


    @property
    def left(self):
        return self._left


   @left.setter
   def left(self,data):
        if data is None:
            self._left = None
        else:
            n = BSTNode(data)
            if n.data >= self.data:
                del n
                raise ValueError("Value must be less-than parent!")
            self._left = n


    @property
    def right(self):
        return self._right


    @right.setter
    def right(self,data):
        if data is None:
            self._right = None
        else:
            n = BSTNode(data)
            if n.data < self.data:
                del n
                raise ValueError("Value must be greater-than or equal-to parent!")
            self._right = n


class BST(object):


    def __init__(self):
        self._root = None


    @property
    def root(self):
        return self._root


    @root.setter
    def root(self,value):
        self._root = BSTNode(value)


    def binary_insert(self,list_in):
        self.root = binary_insert(list_in,0,len(list_in) - 1)

现在,我正在尝试实现一个方法binary_insert(self,list_in),在该方法中我将一个排序列表插入到树中,以便树是平衡的(基本上使用二分搜索);但是,root 的左右节点始终为 None,尽管我在函数中明确分配了它们,并且我确信我的索引是正确的,因为我在运行它时会打印以下内容:

> t = BST()
> list_in = [0,1,2,3,4,5,6,7,8]
> t.binary_insert(list_in)
4
1
0
2
3
6
5
7
8

这是我的函数(注意上面类BST中的实例方法binary_insert):

def binary_insert(list_in,imin,imax):
    if imax < imin:
        return None
    imid = int(floor((imax + imin) / 2))
    n = BSTNode(list_in[imid])
    print(n.data)
    n.left = binary_insert(list_in,imin,imid-1)
    n.right = binary_insert(list_in,imid+1,imax)
    return n

我总是返回一个BSTNode,只有当setter 的输入是None 时才返回None,尽管函数运行后树中的唯一节点是root。我怀疑这些属性发生了一些我不明白的事情。我希望对此进行一些澄清。

 > t = BST()
 > list_in = [0,5,12]
 > t.binary_insert(list_in)
 5
 0
 12
 > t.root.data 
 5
 > t.root.left
 None
 > t.root.right
 None

预期:

 > t.root.left.data
 0
 > t.root.right.data
 12

【问题讨论】:

  • 你能澄清你的实际问题是什么吗?输出的哪一部分是您不期望的,而您期望它是什么?

标签: python recursion binary-search-tree


【解决方案1】:

出现问题是因为在所有递归完成并且根被创建为 BSTNode 之后执行以下行 -

self.root = binary_insert(list_in,0,len(list_in) - 1)

也就是最后binary_insert()返回一个BSTNode是根,这调用setterroot,即-

@root.setter
def root(self,value):
    self._root = BSTNode(value)

这会导致 self._root 使用新的 BSTNode 引用进行初始化,其数据与从 binary_insert() 返回的根的数据相同,这将调用 __init__()BSTNode 传入 root 作为争论。而__init__()BSTNode 函数就是这样做的——

def __init__(self,new):
    if type(new) is BSTNode:
        self._data = new.data
    else:
        self._data = new
    self._left = None
    self._right = None

在这里,您将 self._left 设置为 Noneself._right 设置为 None 。因此,正如您所观察到的,根的左值和右值都没有。

有两种方法可以解决这个问题,一种是 -

将您设置 self.root 的行更改为 -

def binary_insert(self,list_in):
    self._root = binary_insert(list_in,0,len(list_in) - 1)

或者您也可以更改 __init__() BSTNode ,这样如果 type(new)BSTNode ,您也可以从 new BSTNode 复制 leftright 值。示例 -

def __init__(self,new):
    if type(new) is BSTNode:
        self._data = new.data
        self._left = new.left
        self._right = new.right
    else:
        self._data = new
        self._left = None
        self._right = None

【讨论】:

  • 现在看来很明显了!谢谢。
【解决方案2】:

看起来您的插入方法正在构建一棵树,但它没有附加到根,并且对树的所有引用都丢失了。

顺便说一句,请注意,您平衡树的方法(选择列表分区的中间部分)仅在列表已排序时才有效。您需要事先对列表进行排序,或者使用更通用的平衡方案,例如 AVL 树或红黑树

【讨论】:

    猜你喜欢
    • 2022-01-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-04-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多