我正在尝试用Java实现一个红黑树,而我的remove()
函数遇到的问题是它抛出NullPointerException
。
首先,我创建一个根并插入我的红黑树,如下所示:
public void create(String word) { root = new RedBlackTree<String>(word); }
public void insert(String word) { root.add(word); }
然后我有一个GUI,我可以选择使用word
删除某个节点。出于某种原因,我必须手动在r-b树中插入我想要删除的相同单词。 (顺便说一下,插入函数会增加一个单词出现变量,只需将节点的数据值加一两。所以每个节点都有一个唯一的单词。)插入后,我可以在没有NullPointerException
的情况下删除它。但是,如果我在手动插入之前尝试删除该单词,则会抛出异常。即使单词基于我的insert()
函数在树中,树也似乎找不到它。
注意:每次插入树时都会有一个键作为单词,并自动以出现1作为数据开始。插入相同的单词会增加出现次数。
删除功能:
public RedBlackTree<E> remove(String c)
{
// find the target node - the node whose value is removed
RedBlackTree<E> target = locate(c);
if (target.isEmpty()) return root();
// determine the node to be disconnected:
// two cases: if degree < 2 we remove target node;
// otherwise, remove predecessor
RedBlackTree<E> freeNode;
if (target.left().isEmpty() ||
target.right().isEmpty()) // simply re-root tree at right
{
// < two children: target node is easily freed
freeNode = target;
} else {
// two children: find predecessor
freeNode = target.left();
while (!freeNode.right().isEmpty())
{
freeNode = freeNode.right();
}
// freeNode is predecessor
}
target.key = freeNode.key; // move value reference
// child will be orphaned by the freeing of freeNode;
// reparent this child carefully (it may be EMPTY)
RedBlackTree<E> child;
if (freeNode.left().isEmpty())
{
child = freeNode.right();
} else {
child = freeNode.left();
}
// if child is empty, we need to set its parent, temporarily
child.setParent(freeNode.parent());
if (!freeNode.isRoot())
{
if (freeNode.isLeftChild())
{
freeNode.parent().setLeft(child);
} else {
freeNode.parent().setRight(child);
}
}
// Assertion: child has been reparented
RedBlackTree<E> result = child.root();
if (freeNode.isBlack()) child.blackFixup();
return result.root();
}
协助功能:
public RedBlackTree(String v)
{
key = v;
data = 1;
parent = null;
left = right = new RedBlackTree<E>();
isRed = false; // roots of tree should be colored black
}
public boolean isEmpty()
{
return key == null;
}
protected RedBlackTree<E> locate(String c)
{
if (isEmpty()) return null;
int relation = c.compareTo(value());
if (relation == 0) return this;
if (relation < 0) return left().locate(c);
else return right().locate(c);
}
public RedBlackTree<E> add(String c)
{
RedBlackTree<E> tree = insert(c); // first, do a plain insert
tree.setRed(); // we insert nodes as red nodes - a first guess
tree.redFixup(); // now, rebalance the tree
return tree.root(); // return new root
}
protected RedBlackTree<E> insert(String c)
{
// trivial case - tree was empty:
if (isEmpty()) return new RedBlackTree<E>(c);
//System.out.println(locate(c));
if (!key.equals(c)) {
// decide to insert value to left or right of root:
if (c.compareTo(value()) < 0) {
// if to left and no left child, we insert value as leaf
if (left().isEmpty()) {
RedBlackTree<E> result = new RedBlackTree<E>(c);
setLeft(result);
return result;
} else {
// recursively insert to left
return left().insert(c);
}
} else {
// if to right and no left child, we insert value as leaf
if (right().isEmpty()) {
RedBlackTree<E> result = new RedBlackTree<E>(c);
setRight(result);
return result;
} else {
// recursively insert to right
return right().insert(c);
}
}
} else {
data++;
return this;
}
}