Java 删除二叉树中的节点
我了解二叉搜索树中删除算法的基础,并创建了以下代码来删除树中的最大值Java 删除二叉树中的节点,java,binary-tree,Java,Binary Tree,我了解二叉搜索树中删除算法的基础,并创建了以下代码来删除树中的最大值 public void DelLargest() { Node<T> del = this; boolean child = this.left.empty(); boolean child2 = this.right.empty(); right.DelLargest(); if(child && child2) this.h
public void DelLargest()
{
Node<T> del = this;
boolean child = this.left.empty();
boolean child2 = this.right.empty();
right.DelLargest();
if(child && child2)
this.head = null;
else if(child == true && child2 == false)
this.head = left;
}
public void delmax()
{
Node del=这个;
boolean child=this.left.empty();
boolean child2=this.right.empty();
对;
if(child和child2)
this.head=null;
else if(child==true&&child2==false)
this.head=左;
}
基本上,我得到的是递归一直运行到“this”是最右边的节点,然后检查两种情况,“this”是一个叶子,还是“this”有一个左边的子节点。(通常与这种算法相关的另一种情况是多余的,因为在查找具有最大值的节点时,我已经尽可能地向右移动了。)我遇到的麻烦是让当前节点指向null或节点左侧的值
注:这就是我的导师所说的“现代”二叉搜索树,其中顶点或“填充”节点和nil或“空”节点是接口节点的两个子类,它们定义了每种类型的特征
我已经设法将问题缩小到没有返回给定节点值的方法这一事实。现在就开始工作,如果您能提供意见,我们将不胜感激。您的想法是正确的。您要做的是保留对最右侧节点父节点和最右侧节点左子节点的引用,以便在删除它时可以附加这两个节点 这是一个迭代的解决方案。这通常比递归更有效,但是如果您想要递归,您应该能够调整它:
public void delLargest() {
// get rightmost node's parent
Node<T> current = root;
while(current.right != null && current.right.right != null) {
current = current.right;
}
// get the rightmost nodes left node
Node<T> left = current.right.left;
// attach the parent and left
current.right = left;
// nothing points to the right most node anymore, so it will be garbage collected
}
public void delmax(){
//获取最右侧节点的父节点
节点电流=根;
while(current.right!=null&¤t.right.right!=null){
current=current.right;
}
//从左节点获取最右边的节点
节点左=当前。右。左;
//将父对象附加到左侧
当前。右=左;
//不再有任何东西指向最右边的节点,因此它将被垃圾收集
}
正如另一个答案中所建议的,您应该使用迭代方法
在BST中,最大值是最右边的节点。
所以,做一次扫描,一直向右走,直到找到一个空值。
在扫描中,跟踪三个节点。(gpnode,pnode,node)。
扫描完成后,您将拥有(gpnode、pnode、null)
现在有2例
案例1:
pnode
是一个叶子。因此,将边(gpnode,pnode)
更改为(gpnode,null)
案例2:(已编辑)
pnode.lChild
不为空。请注意,pnode.rChild
将为空,因为搜索将在该点终止。
现在将边缘(gpnode,pnode)
更改为(gpnode,pnode.lChild)
以下是伪代码:
public class Node
{
long key;
Node lChild;
Node rChild;
}
public void DelLargest()
{
Node gpnode = null;
Node pnode = null;
Node node = root;
while(node != null) // keep going right until a null is reached
{
gpnode = pnode;
pnode = node;
node = node.rChild;
}
if(pnode.lChild == null) // its a leaf node So change the edge (gpnode,pnode) to (gpnode,null)
{
if(gpnode.lChild == pnode)
{
gpnode.lChild = null;
}
else
{
gpnode.rChild = null;
}
}
else // copy lChild's key to this node and delete lChild
{
if(gpnode.lChild == pnode)
{
gpnode.lChild = pnode.lChild;
}
else
{
gpnode.rChild = pnode.lChild;
}
}
}
你应该小心,应该知道你在这里到底在做什么<代码>while(current.right!=null&¤t.right.right!=null)。这看起来没问题,如果更改顺序,则最终会出现
NULLPointerException
。因此,最好使用额外的变量并将优化留给编译器:)这是错误的。考虑一棵树,其中最右边的节点有一个左子树,它是另一个子树的根。复制pnode.lChild的值并将其删除意味着您将永远丢失所有其他节点。你不能复制和删除值,你需要维护树的结构。@BrendanMcKee:你说得对。修复了描述和伪代码。谢谢你指出这一点。