怪不得教材上没有后序的线索二叉树的遍历代码,考研也不考,分类讨论🤮了。。其实vis打个标记会很简洁。。。硬是只用
∗
p
a
r
e
n
t
*parent
∗parent写了半天,应该没什么bug了。。。
二叉树还是不简单啊
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
// (int *p;)==(typedef int *Pint; Pint p;)
typedef struct TBTNode *TBTree;
typedef struct TBTNode{
int data;
int lt,rt;
struct TBTNode *lchild;
struct TBTNode *rchild;
struct TBTNode *parent; // 后续线索二叉树遍历时需要维护父亲
}TBTNode;
void InThread(TBTNode *p,TBTNode *&pre){ //中序
if(p!=NULL){
InThread(p->lchild,pre);
if(p->lchild==NULL) p->lchild=pre,p->lt=1;
if(pre!=NULL&&pre->rchild==NULL) pre->rchild=p,pre->rt=1;
pre=p;
InThread(p->rchild,pre);
}
}
void InVisit(TBTree B){
puts("InVisit");
if(B!=NULL){
TBTNode *p=B;
while(p->lt==0) p=p->lchild;//走到最左下
for(;p!=NULL;){
printf("%d ",p->data);
if(p->rt==1) p=p->rchild; //有线索(没右子树)跳线索,回到祖先
else { //没线索(有右子树) ,访问右子树
p=p->rchild; //走右子树
while(p->lt==0) p=p->lchild;//先访问右子树的最左下
}
}
}
puts("");
}
void PreThread(TBTNode *p,TBTNode *&pre){ //前序
if(p!=NULL){
if(p->lchild==NULL) p->lchild=pre,p->lt=1;
if(pre!=NULL&&pre->rchild==NULL) pre->rchild=p,pre->rt=1;
pre=p;
if(p->lt==0)PreThread(p->lchild,pre); //注意前序可能回溯回来的时候有线索了,不能走线索的路
if(p->rt==0)PreThread(p->rchild,pre);
}
}
void PreVisit(TBTree B){
puts("PreVisit");
if(B!=NULL){
for(TBTNode *p=B;p!=NULL;){
printf("%d ",p->data);
if(p->rt==1) p=p->rchild; //右边有线索,没子树
else{
if(p->lt==0) p=p->lchild; //左边没线索有子树
else p=p->rchild; // 左边有线索,但是右边一定有子树
}
}
}
puts("");
}
void PostThread(TBTNode *p,TBTNode *&pre){ //后序
if(p!=NULL){
PostThread(p->lchild,pre);
PostThread(p->rchild,pre);
if(p->lchild==NULL) p->lchild=pre,p->lt=1;
if(pre!=NULL&&pre->rchild==NULL) pre->rchild=p,pre->rt=1;
pre=p;
}
}
void PostVisit(TBTree B){
puts("PostVisit");
if(B!=NULL){
TBTNode *p=B;
while(p->lt==0||p->rt==0){//走到最下面
if(p->lt==0) p=p->lchild;//优先走左边
else p=p->rchild;
}
for(;p!=NULL;){
printf("%d ",p->data);
if(p->rt==1) p=p->rchild; //右边有线索,没子树
else { //没线索(有右子树)
TBTNode *q=p->parent;
if(q==NULL) break; // p到根了
if(q->lt==0&&q->lchild==p){ // p是q的左儿子
if(q->rt==0){ //右边有子树访问右边
q=q->rchild;
p=q;
while(p->lt==0||p->rt==0){//走到最下面
if(p->lt==0) p=p->lchild;//优先走左边
else p=p->rchild;
}
}
else {
p=p->parent; //到父亲肯定可以被线索
}
}
else { //p是q的右儿子
p=p->parent;
printf("%d ",p->data);
while(p!=NULL){
p=p->parent;
if(p==NULL) break;
if(q->rt==0){ //走到有右儿子的,否则一直走
p=p->rchild;
while(p->lt==0||p->rt==0){//走到最下面
if(p->lt==0) p=p->lchild;//优先走左边
else p=p->rchild;
}
break;
}
printf("%d ",p->data);
}
}
}
}
}
puts("");
}
void dfs(TBTNode *p,TBTNode *&pre){
if(p!=NULL){
p->parent=pre;
if(p->lt==0)dfs(p->lchild,p);
if(p->rt==0)dfs(p->rchild,p);
}
}
TBTree buildTBT(){
int x;scanf("%d",&x);
TBTNode *b;
b=NULL;
if(x==-1) {
return b;
}
b=(TBTNode*)malloc(sizeof(TBTNode));
b->data=x;b->lt=0;b->rt=0;
b->lchild=buildTBT();
b->rchild=buildTBT();
return b;
}
//1 3 7 10 -1 -1 -1 6 -1 11 -1 -1 5 -1 8 -1 -1
int main(){
// TBTNode *b=buildTBT();
// TBTNode *b1=buildTBT();
TBTNode *b2=buildTBT();
// TBTNode *p=NULL;
// TBTNode *p1=NULL;
TBTNode *p2=NULL;
// InThread(b,p);p->rchild=NULL;p->rt=1;
// InVisit(b);
// PreThread(b1,p1);p1->rchild=NULL;p1->rt=1;
// PreVisit(b1);
PostThread(b2,p2); //出来到根节点,不一定没有右儿子
if(b2->rchild==NULL) b2->rt=1,b2->rchild=NULL;
p2=NULL;
dfs(b2,p2);
PostVisit(b2);
return 0;
}