二进制搜索树 - 插入函数

时间:2012-11-03 01:47:56

标签: python

晚上好,

我的任务是在Python中设计一个能够构建二进制搜索树的函数。 当我自己完成这个功能时,它似乎很有意义,它应该工作。但是,无论出于何种原因,它只构建最后一个“树”而不保存任何先前的树信息。我已经包括了我的类,构造函数以及函数。任何提示表示赞赏!要测试该功能,我使用以下行:

newMap = mapInsert1('one', 1, mapInsert1('two', 2, mkEmptyMap()))


///CODE///
class EmptyMap():
    __slots__ = ()

class NonEmptyMap():
    __slots__ = ('left', 'key', 'value', 'right')

def mkEmptyMap():
    return EmptyMap()

def mkNonEmptyMap(left, key, value, right):
    nonEmptyMap = NonEmptyMap()
    nonEmptyMap.left = left
    nonEmptyMap.key = key
    nonEmptyMap.value = value
    nonEmptyMap.right = right

    return nonEmptyMap

def mapInsert1(key, value, node):
    if isinstance(node, EmptyMap):
        node = mkNonEmptyMap(mkEmptyMap(), key, value, mkEmptyMap())
        return node
    else:
        if key > node.key:
            return mapInsert1(key, value, node.right)
        elif key < node.key:
            return mapInsert1(key, value, node.left)
        elif key == node.key:
            node.value = value
            return mapInsert1(key, value, node)
        else:
            raise TypeError('Bad Map')

1 个答案:

答案 0 :(得分:2)

好的,我在这里得到你的回答。您的逻辑本身没有问题,只是您尝试在Python中实现算法的问题。

您尝试实施算法时遇到了一些问题。第一个与变量如何传递到函数有关。我建议阅读这个StackOverflow Question here,讨论如何将变量传递给函数Python。简而言之,由于您在代码中传递和更新变量的方式,您始终更新变量的本地范围副本,这实际上不会影响您要更新的变量。

要在代码中查看此内容,请尝试以下操作:

>>> newMap = mapInsert1('one', 1, mapInsert1('two', 2, mkEmptyMap()))

正如你所说,这不起作用。但这样做:

>>> newMap = mapInsert1('one', 1, mkEmptyMap())
>>> newMap.right = mapInsert1('two', 2, mkEmptyMap()))

但这不是很有帮助,因为在尝试添加新节点之前,您必须知道要更新的节点。

为了修复你的代码,我所做的就是清理你的类实现。我做了以下更改:

  1. 首先,我开始使用适当的构造函数。 Python类使用 init 函数作为构造函数。有关详细信息,请参阅here
  2. 其次,我添加了插入功能。这实际上解决了你的问题。使用此函数意味着您不会覆盖本地范围的变量,而是改变外部变量。再次,看看我上面链接的变量传递问题,了解更多细节。
  3. 第三,我使空映射只是地图类的空实例化,并删除了isinstance()检查。在Python中,通常最好尽可能避免使用isinstance。 Here是关于避免isinstance的更多信息
  4. 第四,我修复了代码中的无限循环错误。如果查看elif key == node.key条件,则再次使用相同的参数调用mapInsert1,这将为您提供无限的递归循环。
  5. 以下是生成的代码:

    class Map():
        __slots__ = ('left', 'key', 'value', 'right')
    
        def __init__(self, left, key, value, right):
            self.left = left
            self.key = key
            self.value = value
            self.right = right
    
        def insert(self, left, key, value, right):
            self.left = left
            self.key = key
            self.value = value
            self.right = right
    
        def isEmpty(self):
            return self.left == self.right == self.key == self.value == None
    
    def mkEmptyMap():
        return Map(None, None, None, None)
    
    def mapInsert1(key, value, node):
        if node.isEmpty():
            print '0'
            node.insert(mkEmptyMap(), key, value, mkEmptyMap())
            return node
        else:
            if key > node.key:
                print '1'
                return mapInsert1(key, value, node.right)
            elif key < node.key:
                print '2'
                return mapInsert1(key, value, node.left)
            elif key == node.key:
                print '3'
                node.value = value
                return node
            else:
                raise TypeError('Bad Map')
    

    这是一个快速测试:

    >>> root = mapInsert1('five', 5, mkEmptyMap())
    >>> mapInsert1('four', 4, root)
    >>> mapInsert1('ace', 1, root)
    >>> mapInsert1('five', 'five', root)
    >>> root.left.isEmpty()
    Out: False
    >>> root.left.key
    Out: 'ace'
    >>> root.left.value
    Out: 1
    >>> root.right.isEmpty()
    Out: False
    >>> root.right.key
    Out: 'four'
    >>> root.right.value
    Out: 4
    >>> root.key
    Out: 'five'
    >>> root.value
    Out: 'five'