【问题标题】:BST remove node method "cuts off" rest of treeBST 删除节点方法“切断”树的其余部分
【发布时间】:2016-05-31 07:31:02
【问题描述】:

我想编写一个从二叉搜索树中删除节点的方法。

这是我的方法:

public void remove(Node node)
	//Removes a given node and puts one of the nodes below it in its place until it reaches the end
	{
		
		if (node.left != null) //If the node to the left is not empty
		{
			node.value = node.left.value; //Moves up the left node to take its place
			remove(node.left); //Goes to the next node
			if (node.left.right == null && node.left.left == null)
				node.left = null; //Removes the last node at the end of the tree after moving it up
		}
		else if (node.right != null) 
		{
			node.value = node.right.value; //Moves up the left node to take its place
			remove(node.right); //Goes to the next node
			if (node.right.left == null && node.right.right == null)
				node.right = null; //Removes the last node at the end of the tree after moving it up
			
		}	
		
	}

问题是它只在某些情况下有效。

例如,我输入 60、70、65。(根节点为 50) 树应该看起来像

   50
  /  \
     60
    /   \
        70
       /  \
      65

然后假设我选择删除 60。起初这似乎工作正常。 但是,如果我随后运行我信任的搜索方法,则返回 70 在它的任何指针处都没有节点。

我假设正在发生的是在 65 可以向上移动之前将 70 设置为 null。并且由于 65 在技术上不再连接到树,因此搜索方法无法找到它。

所以是这样的:

   50
  /  \
     70
    /   \

       /  \
      65

问题是,我不明白这是怎么发生的。特别是因为如果它的两个指针都指向null,它应该将节点设置为null,由于if语句

if (node.left.right == null && node.left.left == null)
                node.left = null;

if (node.right.left == null && node.right.right == null)
                node.right = null;

另外,如果第一个 if 语句不正确(如果 left != null),它不应该简单地继续插入“else”(并删除右边的)吗?

非常欢迎任何建议或提示。

【问题讨论】:

  • 帮自己一个忙,将 BST 代码与 Swing 代码分开。为您的 BST 编写单元测试并确保其正常工作,然后将其连接到前端。
  • 我不知道如何在这里制作一棵树,但拿你原来的树并将 65 放在 60 所在的位置。我认为不可能有一棵像你认为的那样的树。
  • @Marichyasana 示例的树是正确的 BST;修改后的结果不是。

标签: java tree binary-search-tree


【解决方案1】:

您的删除方法的逻辑存在很大缺陷。首先,您不是在移动节点而是在复制值,这已经是不正确的:因为任何节点都可以有两个链接,因此只复制左侧或右侧的链接值,然后检查您是否在叶子上最终删除它是错误的:如果你不在一片叶子上怎么办?你留下的另一个链接呢?在您的情况下,您最终将获得 70 右侧的值 65:不再是 BST。请记住,规则是对于任何节点 n,左子树中的所有节点都必须小于 n,而右子树中的所有节点必须大于 n。

这也是你找不到 65 的原因:这不是因为 70 像你想的那样附加了两个空指针,而是因为你的搜索方法,当它到达 70 时,因为它大于 65 ,在节点 70 的 left 处搜索 65,并在那里找到一个空值。

这是删除 BST 中节点的正确且经典的 Hibbard 算法:要删除节点 x,您必须将其替换为其后继。它的继任者是谁?因为 x 有一个右孩子,所以它的后继节点是其右子树中键最小的节点。替换保留了树中的顺序,因为 x.key 和后继键之间没有键。我们分四步完成将 x 替换为其后继者的任务:

  • 保存到要删除的节点的链接

  • 设置 x 指向它的后继 min(t.right)。

  • 设置x的右链接(应该指向BST 包含所有大于 x.key) 到 deleteMin(t.right) 的键, 链接到包含所有大于 x.key 的密钥的 BST
    删除后。 (要删除最小值,我们向左走,直到找到一个左链接为空的节点,然后用其右链接替换该节点的链接)

  • 将 x 的左链接(为空)设置为 t.left(所有键 小于删除的密钥及其后继密钥)。

【讨论】:

    猜你喜欢
    • 2021-04-06
    • 1970-01-01
    • 2014-05-26
    • 2023-03-22
    • 2018-10-11
    • 1970-01-01
    • 2016-11-11
    相关资源
    最近更新 更多