有n个结点的二叉树必然有n+1个空链域。(n个结点的二叉树有n-1个链域)
线索二叉树中的规定:
1.如果结点有左孩子,让其lchild指向左孩子;否则,让其lchild指向其前驱
2.如果结点有右孩子,让其rchild指向右孩子;否则,让其rchild指向其后继
这样就需要在原有的二叉树结点结构上,增加两个域
lchild
ltag
data
rtag
rchild
定义:
typedef enum{Link,Thread}PointerTag;
typedef struct BiThrNode
{
TElemType dat;
struct BiThrNode *lchild, *rchild;
PointerTag LTag,RTag;
}BiThrNode, *BiThrTree;
在二叉树的线索链表上添加一个头结点,并令其lchild指向二叉树的头结点,rchild指向遍历访问的最后一个结点。
线索二叉树的遍历:找到序列的第一个结点,依次找结点后继直至其后继为空为止。
线索二叉树的中序遍历:
//中序遍历,先遍历结点的左子树,然后尽力遍历其带后继线索的结点,直到没有后继线索,转入其右子树
Status InOrderTraverse_Thr(BiThrTree T,Status (*Visit)(TElemType e))
{
p = T->lchild;
while(p != T)
{
//访问其左子树为空的结点
while(p -> lTag == Link)
{
p = p-> lchild;
visit(p);
}
//访问后继结点,只要有后继,放心遍历,直到没有后继标记,即rtag== link,
//那么就需要指向它的右子树
while(p->RTag == Thread && p != T){ p = p->rchild; visit(p);}
p = p->rchild;
}
return OK;
}
中序线索化:
线索化过程实际上就是在遍历的过程中修改空指针的过程。
附设全局指针pre始终指向刚刚访问过的结点。
Status InOrderThreading(BiThrTree &Thrt, BiThrTree T)
{
//初始化头结点
Thrt = (BiThrTree)malloc(sizeof(BiThrNode));
if(Thrt) exti(OVERFLOW);
Thrt -> LTag = Link;
Thrt -> RTag = Thread; Thrt ->rchild = Thrt;
if(!T) Thrt->lchild =Thrt;
else
{
//头结点指向根节点
Thrt->lchild = T;
pre = Thrt;
InThreading(T);//在InThreading中pre会改变,只要把它定义为全局的静态变量
pre -> RTag = Thread; pre->rchild = Thrt;
Thrt->rchil = pre;
}
}
void InThreading(BiThrTree p)
{
if(p)
{
InThreading(p->lchild);
if(!p->lchild) {p->LTag = Thread; p->lchild = pre;}
if(!pre->rchild) {pre->RTag = Thread; pre->rchild = p;}
InThreading(p->rchild);
}
}