线索二叉树又可以称为穿线二叉树,创建其目的在于能使遍历更加方便
线索二叉树王相对于普通二叉树:增加额ltag和rtag这两个变量
初始的两值都是置为0的
在创建线索二叉树中,只要是左右任意节点为空,则将对应的ltag(LeftChild's tag)或rtag(RightChild's tag)置为1
这里记住:只要是被置为1的tag的变量,其对应的指针就变成了前驱或者是后继指针,而不再是指向左孩子或者是右孩子的指针
举个例子:
C这个节点的ltag和rtag被置为了1:
就说明C的左指针由原先的闲置空指针(NULL)改成了指向其直接前驱的指针,指向其前驱B
C的右指针从空指针(NULL)改为了指向其直接后继D
那么我们再一次遍历这个改装过的二叉树的时候:
当发现遍历的当前节点rtag==1(存在后继节点)的时候,就直接可以调用right指针找到其下一个节点了
以后将补充如何遍历线索二叉树
Node *pre=NULL; void inthread(Node *p) { if(p!=NULL) { inthread(p->left); if(p->left==NULL) { p->ltag=1; p->left=pre; } if(pre!=NULL&&pre->right==NULL) { pre->rtag=1; pre->right=p; } pre=p; inthread(p->right); } } void creatInthread(Node *node) { if(node!=NULL) { inthread(node); pre->right=NULL; pre->rtag=1; } } Node* next(Node *p) { Node *q=NULL; if(p->rtag==1) q=p->right; else { q=p->right; while(q->ltag==0) q=q->left; } return q; } void RunInthread(Node *node) { if(node==NULL) return; Node *p=node; if(p!=NULL) { while(p->ltag==0) { p=p->left; } printf("%d ",p->data); while(p->right!=NULL) { p=next(p); printf("%d ",p->data); } } }
接下来再写一下线索二叉树是如何遍历的:
我们上面说过,线索二叉树在某些节点的rtag==1;
我们可以直接根据rtag来寻找其后继节点
但是某些节点的tag==0,无法通过指针找到其直接后继节点:
这个时候我们观察图像就会发现:
某个拥有左右子树的节点,其后继节点都是都是他的右子树的最左边的一个儿子或者孙子节点