线索二叉树
结点结构定义如下:
若结点有左子树,则LChild域仍指向其左孩子;
否则,LChild域指向其某种遍历序列中的直接前驱结点。
若结点有右子树,则RChild域仍指向其右孩子;
否则,RChild域指向其某种遍历序列中的直接后继结点。
Ltag
0: LChild域指示结点的左孩子
1: LChild域指示结点的遍历前驱
Rtag
0: RChild域指示结点的右孩子
1: RChild域指示结点的遍历后继
线索二叉树的结点结构:
二叉树的中序线索化
void Inthread(BiTree root)
{ if(root!=NULL)
{
Inthread(root->LChild);/*线索化左子树*/
if(root->LChild == NULL)
{
root->LChild = pre;
root->Ltag = 1; /*置前驱线索*/
}
if(pre != NULL && pre->RChild == NULL)
{
pre->RChild = root;
pre->Rtag = 1; /*置后继线索*/
}
pre = root; /*记录当前访问结点,将成为下一个访问节点的前驱*/
Inthread(root->LChild);/*线索化右子树*/
}
}
先序、后序线索化也类似。
在线索二叉树中查找前驱和后继结点
线索二叉树有三种类型,分别为先序、中序、后序。
利用建立的线索二叉树找某个节点的前驱或者后继,仍不能有效解决先序线索二叉树找先序前驱和后序线索二叉树找后序后继。
每个节点中存着自己的值,左孩子或者直接前驱和右孩子或者直接后继,我们从每个节点只能向下查找来找直接前驱或者直接后继,时间复杂度为O(n)。
若去遍历该节点的祖先节点,也可以找到先序的直接前驱和后序的直接后继,但是不建立线索二叉树通过遍历也可以找到它的直接前驱和直接后继,这两种情况就不用用线索二叉树去考虑了。所以线索二叉树不能有效解决先序线索二叉树找先序前驱和后序线索二叉树找后序后继。
4种可行情况代码
/*先序线索二叉树找后继*/
BiThrTree PreNext(BiThrThee p)
{
if(p->Rtag == 1)
next = p->RChild;
else if(p->LChild){
next = p->LChild;
}else{
next = p->RChild;
}
return next;
}
/*中序线索二叉树找前驱*/
BiThrTree InPre(BiThrThee p)
{
if(p->Ltag == 1)
pre = p->LChild;
else{
for(q=p->LChild;q->Rtag==0;q=q->RChild)
pre = q;
}
return pre;
}
/*中序线索二叉树找后继*/
BiThrTree InNext(BiThrThee p)
{
if(p->Rtag == 1)
next = p->RChild;
else{
for(q=p->RChild;q->Ltag==0;q=q->LChild)
next = q;
}
return next;
}
/*后序线索二叉树找前驱*/
BiThrTree PostPre(BiThrThee p)
{
if(p->Ltag == 1)
pre = p->LChild;
else if(p->RChild){
pre = p->RChild;
}else{
pre = p->LChild;
}
return pre;
}