二叉排序树的构建和插入在这里,请先看这个再看查找和删除。
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;
}
}
}删除节点时,需要通过查找得到删除的节点和它的父节点。在删除节点下面的子节点中找一个替换他自己的节点,一个就是前驱一个就是后继了。这里考虑的是前驱。
分两种情况:
一种是,目标节点只有一个或没有子节点没有,只需要将存在的子节点替换掉目标节点就行了,因为但从一边的子树来讲本身就是一个完整的有序的。
另一种是,左右都存在的,直接需要找到前驱了,遍历左子树的右结点,找到最大的节点,移除这个最大的节点,注意这个节点可能存在的左子树要对接上它的父节点。然后将目标节点替换成这个最大的节点,也要注意对接上左右子树。