BST删除节点方法“切断”树的其余部分

时间:2016-05-31 07:31:02

标签: java tree binary-search-tree

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

这是我的方法:

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语句不为真(如果留下!= null),那么它不应该只是继续使用“else”(并删除正确的语句)吗?

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

1 个答案:

答案 0 :(得分:1)

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

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

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

  • 在t

  • 中保存指向要删除的节点的链接
  • 将x设置为指向其后继min(t.right)。

  • 设置x的右侧链接(应该指向BST 包含大于x.key的所有键)deleteMin(t.right),. 链接到包含所有大于x.key的键的BST 删除后。 (要删除最小值,我们向左移动,直到找到具有空左链接的节点,然后通过其右侧链接替换该节点的链接)

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

enter image description here