Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ssl/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
python BST插入的问题_Python_Binary Tree - Fatal编程技术网

python BST插入的问题

python BST插入的问题,python,binary-tree,Python,Binary Tree,在下面的代码中,我想不出如何执行_inserthelp函数。其他一切似乎都很顺利。。。它目前无法按预期工作。当前函数可以添加第一个节点(根节点)和第二个节点,即root.left。在那之后它就不起作用了 任务说明: 在本练习中,将为您提供一个二进制搜索树的实现。 在练习包中找到的类BST,包含这些方法 insert和find可用于插入和查找键值 对。 这些方法使用两种递归辅助方法\u inserthelp和 \u发现有助于正常工作。 您的任务是实现这些助手方法。 此外,您应该实现方法\u vis

在下面的代码中,我想不出如何执行_inserthelp函数。其他一切似乎都很顺利。。。它目前无法按预期工作。当前函数可以添加第一个节点(根节点)和第二个节点,即root.left。在那之后它就不起作用了

任务说明:

在本练习中,将为您提供一个二进制搜索树的实现。 在练习包中找到的类
BST
,包含这些方法
insert
find
可用于插入和查找键值 对。 这些方法使用两种递归辅助方法
\u inserthelp
\u发现有助于正常工作。
您的任务是实现这些助手方法。
此外,您应该实现方法
\u visit\u inorder
,该方法返回 按顺序生成树节点的迭代器。 您无需更改这3个方法之外的代码即可获得完整的 要点。 '''

代码:

类节点:

def __init__(self, key, value=None):
    self.key = key
    self.value = value
    self.left = None
    self.right = None

def height(self):
    """Return the height of this node."""
    left_height = 1 + self.left.height() if self.left else 0
    right_height = 1 + self.right.height() if self.right else 0
    return max(left_height, right_height)

def __repr__(self):
    return "<BSTNode: key={!r}, value={!r}, id={}>".format(self.key, self.value, id(self))
BST级:

def __init__(self, NodeClass=BSTNode):
    self.BSTNode = NodeClass
    self.root = None
    self.nodes = 0
    #​​‌​‌​​‌‌‌​​‌​ Updated after each call to insert
    self.newest_node = None

def find(self, find_key):
    """Return node with key find_key if it exists. If not, return None. """
    return self._findhelp(self.root, find_key)

def insert(self, new_key, value=None):
    """Insert a new node with key new_key into this BST,
    increase node count by one and return the inserted node."""

    if self.find(new_key) is not None:
        raise KeyError("This BST already contains key {0!r}".format(new_key))

    if self.root == None:
        self.root = self._inserthelp(self.root, new_key, value)
        self.newest_node = self.root
    else:
        self.newest_node = self._inserthelp(self.newest_node, new_key,value)
    
    self.nodes += 1

    return self.newest_node

def height(self):
    """Return the height of this tree."""
    return self.root.height() if self.root else -1

def __iter__(self):
    """Return an iterator of the keys of this tree in sorted order."""
    for node in self._visit_inorder(self.root):
        yield node.key

def __len__(self):
    return self.nodes


#​​‌​‌​​‌‌‌​​‌​ Implement the methods below.

def _findhelp(self, node, find_key):
    """Starting from node, search for node with key find_key and return that node.
    If no node with key find_key exists, return None."""
    inorderlist = self._visit_inorder(node)
    for _node in inorderlist:
        if _node is None or find_key == _node.key:
            return _node
            #​​‌​‌​​‌‌‌​​‌​ End search
    
    return None
    #​​‌​‌​​‌‌‌​​‌​ Implement functionality to recursively choose the next node

def _inserthelp(self, node, new_key, value):
    """Starting from node, find an empty spot for the new node and
    insert it into this BST."""

    if node is None:
            self.newest_node = BSTNode(new_key,value)
    else:
        # Do level order traversal until we find 
        # an empty place. 
        tree = []
        tree.append(node)
        node = tree[0]
        tree.pop()
        while len(tree):
            if (not node.left):
                node.left = BSTNode(new_key,value)
                self.newest_node = BSTNode(new_key,value)
                break
            else:
                tree.append(node.left) 
    
            if (not node.right):
                node.right = BSTNode(new_key,value)
                self.newest_node = BSTNode(new_key,value)
                break
            else:
                tree.append(node.right)

    return self.newest_node


def _visit_inorder(self, starting_node):

    def inorder(node,indorderlist):
        if node is None:
            return
        else:
            inorder(node.left, inorderlist)
            indorderlist.append(node)
            inorder(node.right, inorderlist)


    inorderlist = []
    inorder(starting_node, inorderlist)
    return inorderlist
测试人员:

类Test1BSTNode(unittest.TestCase):

类Test2EmptyBST(unittest.TestCase):

类test3tenodesbst(unittest.TestCase):

类Test4BSTProperty(unittest.TestCase):

如果name='main':
unittest.main(verbosity=2)

您的代码非常大,很难理解,但是我认为,您正在尝试在最后一个条目中插入新的键。但这并不总是有效的。假设你有这个,英国夏令时

  5
 / \
3   7
这里,5、3和7依次插入。最后一个条目是7。所以,如果你想在这里插入4,你必须将它插入3,而不是最后一个条目7。所以用你的方法是行不通的

因此,解决方案是将其插入根中,如下所示

      5
     / \
    3   7
     \
      4
但我仍然不能100%确定这是否是代码中的问题。对我来说,这是一个需要消化的大型未注释代码

def setUp(self):
    self.tree = BST()

def test1_bst_init_node_class(self):
    """BSTs are initialized with a node class. (0p)."""
    self.assertIs(
        self.tree.BSTNode,
        BSTNode,
        "When no node class is specified, the BST should use the class BSTNode as the node class."
    )

def test2_empty_size(self):
    """An empty BST has a size equal to zero. (0p)"""
    tree_size = len(self.tree)
    self.assertEqual(
        0,
        tree_size,
        "Calling len on a tree containing no nodes should return 0, not {}"
        .format(tree_size)
    )

def test3_empty_find(self):
    """Searching for a key in an empty BST returns None. (0p)"""
    self.assertIsNone(
        self.tree.find(1),
        "Calling find in an empty BST should return None."
    )

def test4_empty_insert(self):
    """Calling insert on an empty tree returns the inserted node and adds it to the tree. (0p)"""
    new_key = 1
    new_value = "value"

    inserted_node = self.tree.insert(new_key, new_value)
    self.assertIsInstance(
        inserted_node,
        BSTNode,
        "tree.insert should return an instance of BSTNode, not {0!r}."
        .format(inserted_node)
    )
    self.assertEqual(
        inserted_node.key,
        new_key,
        "Calling tree.insert({0}, {1}) should return a node with the key {0}, not {2}."
        .format(new_key, new_value, inserted_node.key)
    )
    self.assertIs(
        inserted_node.value,
        new_value,
        "Calling tree.insert({0}, {1}) should return a node with the value {1}, not {2}."
        .format(new_key, new_value, inserted_node.value)
    )

    tree_size = len(self.tree)
    self.assertEqual(
        tree_size,
        1,
        "Calling len on a tree containing one key should return 1, not {}"
        .format(tree_size)
    )

def test5_find_one(self):
    """Calling find for a node which exists should return that node. (1p)"""
    node = BSTNode(2)
    node.left = BSTNode(1)
    node.right = BSTNode(3)
    self.tree.root = node

    for node in (node, node.left, node.right):
        found_node = self.tree.find(node.key)
        self.assertIs(
            found_node,
            node,
            "If {0!r} exists in tree, calling tree.find({1}) should return that node, not {2!r}"
            .format(node, node.key, found_node)
        )
def setUp(self):
    self.tree = BST()
    self.keys = random.sample(range(1, 11), 10)

def test1_insert_ten_nodes(self):
    """Inserting ten nodes into a BST should increase its size by ten. (1p)"""
    for key in self.keys:
        inserted_node = self.tree.insert(key)
        self.assertIsInstance(
            inserted_node,
            BSTNode,
            "tree.insert should return an instance of BSTNode, not {0!r}."
            .format(inserted_node)
        )
        self.assertEqual(
            inserted_node.key,
            key,
            "Calling tree.insert({0}) should return a node with the key {0}, not {1}."
            .format(key, inserted_node.key)
        )

    correct_size = len(self.keys)
    returned_size = len(self.tree)

    self.assertEqual(
        correct_size,
        returned_size,
        "Calling len on a tree with {0} nodes should return {0}, not {1}"
        .format(correct_size, returned_size)
    )


def test2_find_ten_nodes(self):
    """All keys which have been inserted should be found by the find method. (1p)"""
    for key in self.keys:
        self.tree.insert(key)

    for key in self.keys:
        returned_node = self.tree.find(key)
        self.assertIsNotNone(
            returned_node,
            "Calling find for an existing key {0} should return the node holding the key, not None"
            .format(key)
        )
        self.assertEqual(
            returned_node.key,
            key,
            "Calling find for an existing key {0} should return the node holding the key, not {1!r}."
            .format(key, returned_node)
        )
def setUp(self):
    self.tree = BST()

def test1_smaller_values_go_left(self):
    """Adding values in sorted descending order creates internal nodes with only left children. (1p)"""
    #​​‌​‌​​‌‌‌​​‌​ Insert nodes with keys 10, 9, 8, ... , 1
    for key in range(10, 0, -1):
        self.tree.insert(key)

    #​​‌​‌​​‌‌‌​​‌​ Starting from the root, traverse down towards the leaf, checking
    #​​‌​‌​​‌‌‌​​‌​ both children of each node
    node = self.tree.root
    for key in range(10, 1, -1):
        self.assertEqual(
            key,
            node.key,
            "After inserting keys in range 10, 9, ... , 2, 1 and then iterating in that range, expected the keys of all the left nodes starting from the root follow this sequence, but a node {0} with the key {1} was found."
            .format(node, node.key)
        )
        #​​‌​‌​​‌‌‌​​‌​ There should not be a right child
        self.assertIsNone(
            node.right,
            "Adding keys in order 10, 9, .. , 2, 1 should not create nodes with right children, but a node {0} with a right child {1} was found."
            .format(node, node.right)
        )
        #​​‌​‌​​‌‌‌​​‌​ There should be a left child
        self.assertIsNotNone(
            node.left,
            "Adding keys in order 10, 9, .. , 2, 1 should only create nodes with left children, but a node {0} with no left child was found."
            .format(node)
        )
        #​​‌​‌​​‌‌‌​​‌​ Go left to next node
        node = node.left

    #​​‌​‌​​‌‌‌​​‌​ The last node is a leaf
    self.assertIsNone(
        node.left,
        "After adding nodes in range 10, 9, ... , 2, 1, the node with key 1 should be a leaf, but it had a left child {0}."
        .format(node.left)
    )
    self.assertIsNone(
        node.right,
        "After adding nodes in range 10, 9, ... , 1, the node with key 1 should be a leaf, but it had a right child {0}."
        .format(node.right)
    )


def test2_larger_values_go_right(self):
    """Adding values in sorted ascending order creates internal nodes with only right children. (1p)"""
    #​​‌​‌​​‌‌‌​​‌​ Insert nodes with keys 1, 2, ... , 10
    for key in range(1, 11):
        self.tree.insert(key)

    #​​‌​‌​​‌‌‌​​‌​ Starting from the root, traverse down towards the leaf, checking
    #​​‌​‌​​‌‌‌​​‌​ both children of each node
    node = self.tree.root
    for key in range(1, 10):
        self.assertEqual(
            key,
            node.key,
            "After inserting keys in range 1, 2, ... , 9, 10 and then iterating in that range, expected the keys of all the right nodes starting from the root to follow this sequence, but a node {0} with the key {1} was found."
            .format(node, node.key)
        )
        #​​‌​‌​​‌‌‌​​‌​ There should not be a left child
        self.assertIsNone(
            node.left,
            "Adding keys in order 1, 2, ... , 9, 10 should not create nodes with left children, but a node {0} with a left child {1} was found."
            .format(node, node.left)
        )
        #​​‌​‌​​‌‌‌​​‌​ There should be a right child
        self.assertIsNotNone(
            node.right,
            "Adding keys in order 1, 2, ... , 9, 10 should only create nodes with right children, but a node {0} with no right child was found."
            .format(node)
        )
        #​​‌​‌​​‌‌‌​​‌​ Go right to the next node
        node = node.right

    #​​‌​‌​​‌‌‌​​‌​ The last node is a leaf
    self.assertIsNone(
        node.left,
        "After adding nodes in range 1, 2, ... , 9, 10, the node with key 10 should be a leaf, but it had a left child {0}."
        .format(node.left)
    )
    self.assertIsNone(
        node.right,
        "After adding nodes in range 1, 2, ... , 9, 10, the node with key 10 should be a leaf, but it had a left child {0}."
        .format(node.right)
    )


def test3_inorder_traversal(self):
    """An inorder traversal visits all nodes in the tree. (1p)"""
    keys = random.sample(range(100), 20)
    inserted = set(self.tree.insert(key) for key in keys)
    visited = set(self.tree._visit_inorder(self.tree.root))

    self.assertSetEqual(
        visited,
        inserted,
        "An inorder traversal should return all nodes which have been added to the tree.\n" +
        "_visit_inorder did not visit the nodes seen above although they were inserted into the tree."
    )


def test4_iter_tree_keys(self):
    """Iterating the tree yields the keys of the tree in sorted ascending order. (1p)"""
    keys = random.sample(range(100), 20)
    for key in keys:
        self.tree.insert(key)

    #​​‌​‌​​‌‌‌​​‌​ Shorter form of [key for key in self.tree]
    #​​‌​‌​​‌‌‌​​‌​ (which is possible because the class BST implements the method __iter__)
    visited = list(self.tree)
    #​​‌​‌​​‌‌‌​​‌​ The returned values should be in sorted ascending order
    correct_order = sorted(keys)

    self.assertListEqual(
        visited,
        correct_order,
        "Calling __iter__ should return an iterator of the keys of the BST in sorted ascending order.\n" +
        "Note: the traversal method should not care in what order the nodes appear, if the insert method is implemented correctly, an inorder traversal will yield the keys in sorted order."
    )


def test5_height_complete_tree(self):
    """The height of a complete tree with n nodes is log_2(n+1) - 1. (1p)"""
    #​​‌​‌​​‌‌‌​​‌​ Add keys so they form a complete tree
    keys = [50, 25, 75, 20, 30, 70, 80]
    for key in keys:
        self.tree.insert(key)

    tree_size = len(self.tree)
    added_count = len(keys)
    self.assertEqual(
        tree_size,
        added_count,
        "Adding {0} keys to an initially empty tree, calling len on the tree should return {0}, not {1}."
        .format(added_count, tree_size)
    )

    #​​‌​‌​​‌‌‌​​‌​ math.log returns float
    self.assertAlmostEqual(
        float(self.tree.height()),
        math.log(len(keys) + 1, 2) - 1,
    )
  5
 / \
3   7
      5
     / \
    3   7
     \
      4