我已经实现了以下方法来删除BST中的节点,以遵循发布于here的示例:
NodeT类
public class NodeT {
int elem;
NodeT left;
NodeT right;
public NodeT(int elem){
this.elem=elem;
}
}
BinaryTree类
public class BinaryTree {
NodoT root;
public void insertElem(int n){
root=addRec(root,n);
}
public NodoT addRec(NodeT n, int elem){
if (n==null){
n=new NodeT(elem);
}
else{
if (elem<n.elem){
n.left=addRec(n.left,elem);
}
else{
n.right=addRec(n.right,elem);
}
}
return n;
}
public void inorder(NodeT n){
if (n!=null){
inorder(n.left);
System.out.println(n.elem);
inorden(n.right);
}
}
public NodeT search(NodeT root, int n){
if (root.elem==n) return root;
else{
if (n<root.elem){
if (root.left!=null){
return search(root.left,n);
}
else return null;
}
else{
if (root.right!=null){
return search(root.right,n);
}
else return null;
}
}
}
public void delete(int n){
root=deleteNode(root,n);
}
public NodeT deleteNode(NodeT curr, int n){
NodoT answ;
answ=search(curr,n);
if (answ==null){
System.out.println("not found");
return curr;
}
else{
if (curr.left==null)return curr.right;
else if (curr.right==null) return curr.left;
curr.elem=minValue(curr.right);
curr.right=deleteNode(curr.right,curr.elem);
}
return curr;
}
int minValue(NodoT curr){
int min=curr.elem;
while (curr.left!=null){
menor=curr.left.elem;
curr=curr.left;
}
return min;
}
//main program
BinaryTree bt=new BinaryTree();
int data[]={50,30,70,20,40,60,80};
for (int i=0;i<data.length;i++){
bt.insertElem(data[i]);
}
bt.inorder(bt.root);
bt.delete(20);
bt.inorder(bt.root);
bt.delete(30);
bt.inorder(bt.root);
bt.delete(50);
bt.inorder(bt.root);
但是,当我进行测试时,它会在第bt.delete(50);
行上打印“ not found”,这是我做错了什么?
答案 0 :(得分:1)
代码中有很多错误,我认为您是从您的语言转换而来的,缺少一些变量名。但是,我更正了名称并测试了代码。
问题:在您的deleteNode()
中,您不会重复执行该树,即检查是否元素小于或大于curr
的值。您需要再添加几条IF
检查。
解决方案::用这个替换您的deleteNode()
。
public NodeT deleteNode(NodeT curr, int n){
NodeT answ;
answ=search(curr,n);
if (answ==null){
System.out.println("not found");
return curr;
}
// need to check whether value is small or greater
if (n < curr.elem)
curr.left = deleteNode(curr.left, n);
else if (n > curr.elem)
curr.right = deleteNode(curr.right, n);
// if value is same, means this is the node to be deleted
else{
if (curr.left==null)
return curr.right;
else if (curr.right==null)
return curr.left;
curr.elem=minValue(curr.right);
curr.right=deleteNode(curr.right,curr.elem);
}
return curr;
}
答案 1 :(得分:0)
public void insertElem(int n){
root=addRec(root,n);
}
每次添加一些值时,您都将覆盖root
,因此在第二次插入时,您会忘记其父级,依此类推,最终您只会知道80,因为这是您插入的最后一个元素,您用来覆盖root
的最后一个值。 root
仅应在null
时初始化,例如
if (root == null) root=addRec(root,n);
public NodoT addRec(NodeT n, int elem){
if (n==null){
n=new NodeT(elem);
}
else{
if (elem<n.elem){
n.left=addRec(n.left,elem);
}
else{
n.right=addRec(n.right,elem);
}
}
return n;
}
您总是将n.left
或n.right
设置为addRec
返回的值,这会破坏您的结构。您可以正确地调用addRec
,但是如果各自的值为n.left
,则只能将其分配给n.right
或null
。
从我们当前的角度看,似乎无关紧要。
看起来不错。
看起来不错。
public NodeT deleteNode(NodeT curr, int n){
NodoT answ;
answ=search(curr,n);
if (answ==null){
System.out.println("not found");
return curr;
}
else{
if (curr.left==null)return curr.right;
else if (curr.right==null) return curr.left;
curr.elem=minValue(curr.right);
curr.right=deleteNode(curr.right,curr.elem);
}
return curr;
}
您没有在比较实际数字。这样的想法应该是,如果值要大于当前节点的值,则将在右分支中搜索要删除的项目,否则将在左分支中进行搜索。如果您需要搜索的分支到达null
,则该项目在树中不存在。请参阅Zain Arshad的实现。我本来可以做类似的事情,但是由于他已经实现了,所以我会参考并赞成它,