公有方法remove应该仅有一个参数(entry), 所以与调用私有递归方法addEntry的方法add一样,remove将调用一个私有递归方法removeEntry。
给removeEntry传递的是树根,而不是树本身。因为该方法可能从树中删除根节点,所以总要保留指向树根的引用。因此给removeEntry再传递外一个参数——oldEntry, 然后在该方法中用删除的项来改变它的值。
所以,removeEntry的头应该是
private BinaryNode<T> removeEntry(BinaryNode<T> rootNode, T entry,
ReturnObject oldEntry)
ReturnObject是一个内部类,它仅有一个数据域,只有方法set和get可以使用。初始化时oldEntry的数据域是null,当在树中没找到该项的时候,remove返回null。
remove的实现:
public T remove(T entry)
{
ReturnObject oldEntry = new ReturnObject(null);
BinaryNode<T> newRoot = removeEntry(getRootNode(), entry, oldEntry);
setRootNode(newRoot);
return oldEntry.get();
}
remove会调用removeEntry,当删除的项在根中,removeEntry调用removeFromRoot来删除;当删除的在根的子树中,removeEntry递归调用自己。
removeEntry的实现:
private BinaryNode<T> removeEntry(BinaryNode<T> rootNode, T entry, ReturnObject oldEntry)
{
if(rootNode!=null)
{
T rootData = rootNode.getData();
int comparison = entry.compareTo(rootData);
if(comparison == 0)
{
oldEntry.set(rootData);
rootNode = removeFromRoot(rootNode);
}
else if(comparison < 0)
{
BinaryNode<T> leftChild = rootNode.getLeftChild();
BinaryNode<T> subtreeRoot = removeEntry(leftChild, entry, oldEntry);
rootNode.setLeftChild(subtreeRoot);
}
else
{
BinaryNode<T> rightChild = rootNode.getRightChild();
rootNode.setRightChild(removeEntry(rightChild, entry, oldEntry));
}
}
return rootNode;
}
removeEntry方法调用removeFromRoot来删除给定子树的根中的项。
如果给定的结点最多只有一个孩子,则可以直接删除该结点和它的项。要删除有两个孩子的结点中的项,必须找到该结点的左子树中的最大项。删除含有该最大项的结点,然后用最大项替代被删除的项。
下面是算法:
Algorithm removeFromRoot(rootNode)
//删除给定子树的根结点中的项
if (rootNode有两个孩子)
{
largestNode = 在rootNode的左子树中有最大项的结点
使用largestNode中的项替换rootNode中的项
从树中删除largestNode
}
else if (rootNode仅有右孩子)
rootNode = rootNode的右孩子
else
rootNode = rootNode的左孩子,//可能是null
//断言:如果rootNode是叶子结点,则它现在是null
return rootNode
removeFromRoot不是递归的,但findLargest和removeLargest都是递归的.
给定子树的根,removeFromRoot返回结点删除后那棵子树的根。
private BinaryNode<T> removeFromRoot(BinaryNode<T> rootNode)
{
if(rootNode.hasLeftChild() && rootNode.hasRightChild())
{
BinaryNode<T> leftSubtreeRoot = rootNode.getLeftChild();
BinaryNode<T> largestNode = findLargest(leftSubtreeRoot);
rootNode.setData(largestNode.getData());
rootNode.setLeftChild(removeLargest(leftSubtreeRoot));
}
else if (rootNode.hasRightChild())
rootNode = rootNode.getRightChild();
else
rootNode = rootNode.getLeftChild();
return rootNode;
}
findLargest:
private BinaryNode<T> findLargest(BinaryNode<T> rootNode)
{
if(rootNode.hasRightChild())
rootNode = findLargest(rootNode.getRightChild());
return rootNode;
}
BinaryNode:
private BinaryNode<T> removeLargest(BinaryNode<T> rootNode)
{
if(rootNode.hasRightChild())
{
BinaryNode<T> rightChild = rootNode.getRightChild();
rightChild = removeLargest(rightChild);
rootNode.setRightChild(rightChild);
}
else
rootNode = rootNode.getLeftChild();
return rootNode;
}