摘要:如何删除一个线索树中的节点,并且不影响线索的指向.基本框架是普通二叉树的删除办法,有一些细节要处理:
【1】依然是注意不要陷入死循环;
======================================
【2】判断节点儿子的情况相对较为复杂:
首先,如果该节点有两个儿子,那么它的没有线索指针。同样,除了整棵线索树只有一个节点的情况(它没有前继与后继),没有线索指针就意味着有两个儿子,那么只需要添加一些其他条件就可以把只有一个节点的特殊情况判断出来,很显然,当两个指针都指向NULL时该节点就是单节点树。
其它所有的情况都是少于两个儿子的。
也可以反过来考虑,当有一个儿子指针为NULL或者有一个以上的线索指针,必然是少于两个儿子的.
======================================
【3】另一个需要注意的地方是线索的处理,也许某个节点被删除以后它的父节点有了一个空指针,这个指针必须指向一个线索.注意到
{1}如果父节点是有两个儿子的,我们选取它左子树的最大节点进行递归删除(像普通二叉树),然后检测该父节点的左儿子是否变成了NULL,如果是,就要找到这个相应的线索.
====================================
{2}如果该父节点只有一个儿子,那么我们确定是哪个儿子(注意这里要区分是儿子而不是线索),然后找到儿子的的前驱后驱代替该儿子,并且删除该儿子。
==================================
那么父节点的儿子被删除后是否会出现应该指向线索但却指向NULL呢?如果儿子的前驱/后继是NULL的话,就可能出现这种情况(因为代替儿子的是它的前驱后继),那说明该儿子是最大节点或者最小节点,那么儿子被删除后相应的最大或最小节点一定是它们的父节点(根据中序遍历很容易证明这一点),因此该父节点任然没有前驱/后继,不需要添加线索.
=============================
[4]还需要注意的一点是,如果某节点被删除后,是否会影响到某些线索指针指向它的节点?假设该节点y是具有两个儿子的节点,那么我们是将它左子树的最大节点代替它,然后递归的删除左子树的最大节点的.很显然,左子树的最大节点就是它的前继。因此原来节点x的后继如果指向y那么x就是它左子树的最大节点,会被递归删除掉,当然没有线索.如果节点z的前继线索指向y,那么z就是y的后继,一定是右子树最小节点,
那么z的线索将指向原来的x(xyz)在y被删除后(xz),这个线索是正确的.
====================================
(3)通过详细(也许啰嗦)的分类分析,按照该算法线索既不会缺少,也不会指向错误.
Position Findmax(Position T)//查找该树的最大值
{
if (T==NULL)
return T;
while(T->Right!=NULL&&T->Rightisthread==Empty)
T = T->Right;
return T;
}
Position Delete(Position T,int x)
{
static Position root = T;
Position Last = NULL;
Position P;
if(T==NULL)
return T;
if(x>T->Element)
T->Right = Delete(T->Right,x);
else if (xElement)
T->Left = Delete(T->Left,x);
else
//找到x
{
if(T->Left==NULL||T->Right==NULL||T->Leftisthread||T->Rightisthread)//少于两个儿子
{
if(T->Left !=NULL&&T->Leftisthread == Empty)
return Findpre(root,Last,NULL,x);
else if(T->Right!=NULL&&T->Rightisthread==Empty)
return Findnext(root,Last,NULL,x);
else
return NULL;
}
else/有两个儿子
{
//处理有两个儿子的节点
P = Findmax(T->Left);//找到X的左子树的最大
T->Element = P->Element;//将X的前继赋给x
T->Left = Delete(T->Left,T->Element);//将T->Element
if(T->Left == NULL)//T的左子树变为NULL需要加thread
{
T->Leftisthread = thread;
T->Left = Findpre(root,Last,NULL,T->Element);//找到P的前继并给T(以前的P)
}
}
}
return T;
}