我正在尝试使用Cormen的伪代码来实现BST算法,但仍然存在问题。
这是我的节点代码:
public class Node { Node left; Node right; int value; Node(int value){ this.value = value; this.left = null; this.right = null; } }
对于Bstree:
public class Btree { Node root; Btree(){ this.root = null; } public static void inorderWalk(Node n){ if(n != null){ inorderWalk(n.left); System.out.print(n.value + " "); inorderWalk(n.right); } } public static Node getParent(Btree t, Node n){ Node current = t.root; Node parent = null; while(true){ if (current == null) return null; if( current.value == n.value ){ break; } if (current.value > n.value){ parent = current; current = current.left; } else{ //(current.value < n.value) parent = current; current = current.right; } } return parent; } public static Node search(Node n,int key){ if(n == null || key == n.value ){ return n; } if(key < n.value){ return search(n.left,key); } else{ return search(n.right,key); } } public static Node treeMinimum(Node x){ if(x == null){ return null; } while(x.left != null){ x = x.left; } return x; } public static Node treeMaximum(Node x){ if(x == null){ return null; } while(x.right != null){ x = x.right; } return x; } public static Node treeSuccessor(Btree t,Node x){ if (x.right == null){ return treeMinimum(x.right); } Node y = getParent(t,x); while(y != null && x == y.right){ x = y; y = getParent(t,y); } return y; } public static Btree insert(Btree t,Node z){ Node y = null; Node x = t.root; while(x != null){ y = x; if(z.value < x.value) x = x.left; else x = x.right; } Node tmp = getParent(t,z); tmp = y; if(y == null){ t.root = z; } else if(z.value < y.value) y.left = z; else y.right = z; return t; } public static Btree delete(Btree t,Node z){ Node y,x; if (z.left == null || z.right == null) y = z; else y = treeSuccessor(t,z); if (y.left != null) x = y.left; else x = y.right; if (x != null){ Node tmp = getParent(t,x); tmp = getParent(t,y); } if (getParent(t,y) == null ){ t.root = x; } else{ if( y == getParent(t,y).left ){ getParent(t,y).left = x; } else{ getParent(t,y).right = x; } } if(y != z){ z.value = y.value; } return t; } public static void main(String[] args){ Btree test = new Btree(); Node n1 = new Node(6); Node n2 = new Node(3); Node n3 = new Node(9); Node n4 = new Node(1); Node n5 = new Node(16); Node n6 = new Node(4); Node n7 = new Node(2); Node n8 = new Node(11); Node n9 = new Node(13); test = insert(test,n1); test = insert(test,n2); test = insert(test,n3); test = insert(test,n4); test = insert(test,n5); test = insert(test,n6); test = insert(test,n7); test = insert(test,n8); test = insert(test,n9); inorderWalk(test.root); System.out.println(); test = delete(test,n8); inorderWalk(test.root); System.out.println(); test = delete(test,n5); inorderWalk(test.root); System.out.println(); test = delete(test,n2); inorderWalk(test.root); System.out.println(); test = delete(test,n1); inorderWalk(test.root); } }
主要问题在于删除部分,有时它按预期工作,有时删除错误,有时出现空指针异常。可能是什么问题?
附言:这不是作业
一些眼前的问题与您的代码:您treeSuccessor开始使用
treeSuccessor
if (x.right == null){ return treeMinimum(x.right); }
if (x.right != null)当然应该是。
if (x.right != null)
您的insert代码包含以下内容
insert
Node tmp = getParent(t,z); tmp = y;
您分配tmp给它的位置,然后立即再次分配给它。在我看来,您根本不需要这些行,因为您将不再使用它们tmp。此时,您已经y是要z插入其子节点的节点,因此只需删除这些行。
tmp
y
z
同样,在中delete,您有
delete
if (x != null){ Node tmp = getParent(t,x); tmp = getParent(t,y); }
您实际上什么都没做的地方,因为tmp在此代码段之外不可见。进一步,在中delete,您重复表达式getParent(t,y),这可能是一个昂贵的操作,因此您应该只计算一次并将其分配给某个变量。
getParent(t,y)
但总的来说,您的代码虽然看起来是正确的(可能与delete,但我不太了解,但看起来很可疑),但它与典型的二叉树代码不太相似。你并不真的需要getParent和treeSuccessor方法来实现search,insert和delete。您具有的基本结构也search适用于其他结构,但进行了以下修改:
getParent
search
null
这两个条件都要求您在下降到树中时跟踪父节点,但这是您需要做的唯一修改search。尤其是,永远不需要在树上向上移动(这样treeSuccessor做就可以了)。