二叉排序树的查找和删除

二叉排序树的构建和插入在这里,请先看这个再看查找和删除。


static void Search(Node head,int data,ref Node targetNode, ref Node preNode)
{
    //查找方法很简单
    targetNode = head;
    preNode = null;

    while (targetNode != null && targetNode.data != data)
    {
        preNode = targetNode;
        if (data < targetNode.data)
        {
            targetNode = targetNode.cLeft;
        }
        else
        {
            targetNode = targetNode.cRight;
        }
    }
}

//删除
static void Delete(ref Node head, int data)
{
    Node targetNode = null;
    Node preNode = null;

    Search(head, data, ref targetNode, ref preNode);
            
    if (targetNode == null) return;

    if (targetNode.cLeft == null || targetNode.cRight == null)
    {
        //有一边的结点为空或两边都空,直接删调
        Node tempTargetNode;
        if (targetNode.cLeft == null)
        {
            tempTargetNode = targetNode.cRight;
        }
        else
        {
            tempTargetNode = targetNode.cLeft;
        }

        if (preNode == null)
        {
            head = tempTargetNode;
            return;
        }

        if (preNode.cLeft == targetNode)//左边
        {
            preNode.cLeft = tempTargetNode;
        }
        else
        {
            preNode.cRight = tempTargetNode;
        }
    }
    else
    {
        //两边都有
        //在左边找一个最大的替换,就是目标的前驱。或则找后继,就是右边中最小的
        Node LeftBig = targetNode.cLeft;
        Node preBig = targetNode;
        while (LeftBig.cRight != null)
        {
            preBig = LeftBig;
            LeftBig = LeftBig.cRight;
        }
                

        preBig.cLeft = LeftBig.cLeft;//删除替换的节点,对接最大节点的左子树
        
        //对接目标节点的左右子树
        if (LeftBig != targetNode.cLeft)//排除特殊情况
        {
            LeftBig.cLeft = targetNode.cLeft;
        }
        LeftBig.cRight = targetNode.cRight;

        if (preNode == null)
        {
            head = LeftBig;
            return;
        }
        if (preNode.cLeft == targetNode)//左边
        {
            preNode.cLeft = LeftBig;
                    
        }
        else
        {
            preNode.cRight = LeftBig;
        }

    }
}


删除节点时,需要通过查找得到删除的节点和它的父节点。在删除节点下面的子节点中找一个替换他自己的节点,一个就是前驱一个就是后继了。这里考虑的是前驱。

分两种情况:

一种是,目标节点只有一个或没有子节点没有,只需要将存在的子节点替换掉目标节点就行了,因为但从一边的子树来讲本身就是一个完整的有序的。

另一种是,左右都存在的,直接需要找到前驱了,遍历左子树的右结点,找到最大的节点,移除这个最大的节点,注意这个节点可能存在的左子树要对接上它的父节点。然后将目标节点替换成这个最大的节点,也要注意对接上左右子树。


首页 我的博客
粤ICP备17103704号