0
点赞
收藏
分享

微信扫一扫

数据结构——二叉搜索树的删除操作

三维控件研究 2022-02-18 阅读 91

        公有方法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;
}
举报

相关推荐

0 条评论