question:如何根据中序遍历序列找到一个结点的前驱
使用土办法:分配两个指针,一个根据遍历找到该结点,一个结点记录该结点的前一个结点
BiNode *p = NULL;
BiNode *pre = NULL;
BiNode *final = NULL;
void findInorder(BiTree T){
if(T!=NULL){
findInorder(T->lchild);
visit(T);
findInorder(T->rchild);
}
}
void visit(BiNode T){
if(p == q){
final = pre;
}
else{
pre = p;
}
}
中序遍历线索化
思路:
首先先判断是否是叶子结点,然后根据土办法找到它的前驱和和后继,通过一个tag标签来判断它的左右子树是否是线索化
typedef struct ThreadNode{
ElemType data;
struct ThreadNode *lchlid,*rchlid;
int ltag,rtag;
}ThreadNode,*ThreadTree;
ThreadNode *pre = NULL;
void findInorder(BiTree T){
if(T!=NULL){
findInorder(T->lchild);
visit(T);
findInorder(T->rchild);
}
pre->rchild = NULL;
pre->rtag = 1;
}
void visit(ThreadNode *T){
if(T->lchild == NULL){
T->ltag = 1;
T->lchild = pre;
}
else if(pre->lchild == NULL && pre!=NULL ){
pre->rtag = 1;
pre->rchild = T;
}
pre = T;
}
先序线索化
因为先序遍历访问顺序是:根->左->右;所以如果将左节点的next指向,pre(根节点),然后再将pre指向左节点,那么会形成回路,解决方法:
再执行线索化的时候,先判断左子树是否是线索化,如果线索化,则跳过,让该结点访问右子树
后序线索化
因为访问根节点的时候一定访问过左右子树,所以不存在回路的问题
如何根据线索化的二叉树中找前驱和后继
-
中序线索二叉树
-
如果有孩子结点,那么后继一定是右子树中最左边的结点
代码:
ThreadNode *findNode(ThreadNode *T){ if(T->ltag == 1){ return T->lchild; } else{ return Firstnode(T->rchild); } } ThreadNode *Firstnode(ThreadNode *p){ while(p->ltag == 0) p = p->lchild; return p; }
-
找前驱
中序线索二叉树的前驱一定是该结点左子树的最后边的结点
-
-
先序线索二叉树
-
找后继,先看右边是否被线索化,如果未被线索化,一定是有右孩子,如果有左孩子就访问左孩子,否则访问右节点
ThreadNode *Firstnode(ThreadNode *p) { if(p->rtag == 1){ return p->rchild; } else{ if(p->ltag == 0){ return p->lchild; } else{ return p->rchild; } } }
-
因为顺序是根,左,右;所以如果未被线索化的结点无法找到前驱;只有三叉二叉树才有可能找到前驱
-
-
后序线索二叉树
- 找后序前驱:如果未被线索化,有右孩子就是前驱,无右孩子有左孩子就是前驱
- 如果不是三叉二叉树,无法找到后继