如果只是单纯的二叉树,只有得到根节点才能完成遍历的序列
如何找到一个结点的指针?
已知结点p
思路
- 从根节点出发,设定一个q结点和pre结点代表q结点的前驱
- pre指针的结点为q结点的前驱,如果q==p,那么pre就是p结点的前驱
- 如果需要找到q结点的后继,那么当pre==p的时候,q就是p的后继了
二叉树线索化
因为链式存储的二叉树,结点为n就会有n+1个空链域,如果全部利用起来,进行线索化,就可以很方便的找到前驱和后继
前驱线索:由左孩子充当
后继线索:由右孩子充当
用ltag,rtag:如果置为1,说明是线索,为0标识为0
在先序线索化中会出现转圈问题,所以,要在访问左子树的时候判断一下,左子树指向的是孩子结点还是左子树
构造的核心思想
- 先序、中序、后续的遍历序列
- 用一个Pre指针来记录当前访问指针的前驱,如果需要标记前驱,那么将其lchild设置为pre,如果需要找到后继结点。将pre->rchild设置为p
易错点:
- 先序遍历中,左子树可能出现转圈的问题,所以需要判断是否已经线索化
- 最后一个结点的rchild的tag需要单独处理
具体代码
#include<stdio.h>
struct ElemType{
int value;
};
typedef struct BiTNode{
ElemType data;
struct BiTNode *lchild,*rchlid;
int ltag,rtag;
}BiTNode,*BiTree;
BiTNode * pre = NULL;
void visit(BiTNode *t){
if(t->lchild==NULL){
t->ltag = 1;
t->lchild = pre;
}
if(pre!=NULL && pre->rchlid==NULL){
pre->rtag = 1;
pre->rchlid = t;
}
pre = t;
}
int PreOrder(BiTree T){
if(T!=NULL){
PreOrder(T->lchild);
visit(T);
PreOrder(T->rchlid);
}
}
void CreateInThead(BiTree t){
if(t!=NULL){
PreOrder(t);
}
if(pre->rchlid==NULL){
pre->rtag = 1;
}
}