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