2.4c 先后序线索二叉树_代码
2.4c 先后序线索二叉树_代码_哔哩哔哩_bilibili
//先序线索二叉树 #include<stdio.h> #include<stdlib.h> #include<stdbool.h> typedef struct ThreadNode{ char data; struct ThreadNode *lchild, *rchild; int ltag, rtag; //左、右线索标记 }ThreadNode, *ThreadTree;//全局变量pre, 指向当前访问结点的前驱 ThreadTree pre=NULL; //建立前驱线索和后继线索 void visit(ThreadTree q){ if(q->lchild==NULL){ q->lchild=pre; //建立当前结点的前驱线索 q->ltag=1; } if(pre!=NULL && pre->rchild==NULL){ pre->rchild=q; //建立前驱结点的后继线索 pre->rtag=1; } pre=q; } //先序线索化二叉树 void PreThread(ThreadTree T){ if(T==NULL) return; visit(T); //访问根节点 if(T->ltag==0) //若T有左子树 PreThread(T->lchild); if(T->rtag==0) //若T有右子树 PreThread(T->rchild); } //建立先序线索二叉树 void CreatePreThread(ThreadTree T){ PreThread(T); //先序线索化二叉树 if(pre->rchild==NULL) pre->rtag=1; //处理最后一个结点 } //找到以p为根的子树中,第一个被先序遍历的结点 ThreadTree FirstNode(ThreadTree p){ return p; } //在先序线索二叉树中找到结点p的后继结点 ThreadTree NextNode(ThreadTree p){ if(p->ltag==0) //若p有左孩子 return p->lchild; //返回左孩子 else return p->rchild; //返回右孩子或右线索 } //输出后继序列 void PreOrderNext(ThreadTree T){ for(ThreadTree p=FirstNode(T); p!=NULL; p=NextNode(p)) printf("%c",p->data); } //先序递归构建二叉树 int sc=0; //全局变量sc, 枚举串 ThreadTree BuildBiTree(char *s){ //s为先序遍历串 ThreadTree T; if(s[sc]=='^') T=NULL; else{ T=(ThreadTree)malloc(sizeof(ThreadNode)); T->data=s[sc++]; T->lchild=BuildBiTree(s); sc++; T->rchild=BuildBiTree(s); } return T; } int main(){ char s[]="ABD^G^^E^^CF^^^"; ThreadTree T=BuildBiTree(s); //先序递归构建二叉树 CreatePreThread(T); //建立先序线索二叉树 PreOrderNext(T); //输出后继序列 return 0; }
// 先序线索二叉树(含双亲指针) #include <stdio.h> #include <stdlib.h> typedef struct ThreadNode { char data; struct ThreadNode *lchild, *rchild; struct ThreadNode *parent; // 双亲指针 int ltag, rtag; // 0 = 孩子指针,1 = 线索 } ThreadNode, *ThreadTree; // ========== 先序线索化 ========== ThreadTree pre = NULL; // 记录当前访问结点的前驱 void PreThread(ThreadTree p) { if (p == NULL) return; if (p->lchild == NULL) { // 左子树空 -> 建前驱线索 p->lchild = pre; p->ltag = 1; } if (pre != NULL && pre->rchild == NULL) { // 为前驱结点建后继线索 pre->rchild = p; pre->rtag = 1; } pre = p; if (p->ltag == 0) PreThread(p->lchild); // 有左孩子才递归,避免线索死循环 if (p->rtag == 0) PreThread(p->rchild); } void CreatePreThread(ThreadTree T) { pre = NULL; if (T != NULL) { PreThread(T); pre->rchild = NULL; //末尾结点后继置空 pre->rtag = 1; } } // ========== 找先序后继========== ThreadTree PreOrderNext(ThreadTree p) { if (p->ltag == 0) return p->lchild; // 有左孩子:左孩子即后继 return p->rchild; // 无左孩子:右孩子或右线索即后继 } // 输出先序的后继序列 void PrintPreOrderNext(ThreadTree T) { for (ThreadTree p = T; p != NULL; p = PreOrderNext(p)) printf("%c ", p->data); printf("\n"); } // ========== 找先序前驱:利用双亲指针 ========== // 求一棵子树先序序列的最后一个结点:优先右孩子,无右孩子才走左孩子 ThreadTree LastNodePreorder(ThreadTree q) { while (q->ltag == 0 || q->rtag == 0) { if (q->rtag == 0) q = q->rchild; else q = q->lchild; } return q; } // 找先序前驱 ThreadTree PreOrderPrev(ThreadTree p) { if (p->ltag == 1) return p->lchild; // ① 左线索就是前驱(叶子/无左孩子) if (p->parent == NULL) return NULL; // ② 根结点没有前驱 ThreadTree parent = p->parent; if (parent->ltag == 0 && parent->lchild == p) return parent; // ③ p 是左孩子:前驱 = 父结点 if (parent->ltag == 0) return LastNodePreorder(parent->lchild); // ④ p 是右孩子且父有左子树:前驱 = 左子树末结点 return parent; // ⑤ p 是右孩子且父无左子树:前驱 = 父结点 } // 输出先序的前驱序列 void PrintPreOrderPrev(ThreadTree T){ for (ThreadTree p = LastNodePreorder(T); p != NULL; p = PreOrderPrev(p)) printf("%c ", p->data); printf("\n"); } // ==========建二叉树========== // 创建字符结点 ThreadTree newNode(char ch) { ThreadTree p = (ThreadTree)malloc(sizeof(ThreadNode)); p->data = ch; p->lchild = p->rchild = p->parent = NULL; p->ltag = p->rtag = 0; return p; } // 挂接左孩子并设置双亲指针 void linkLeft(ThreadTree parent, ThreadTree child) { parent->lchild = child; if (child) child->parent = parent; } // 挂接右孩子并设置双亲指针 void linkRight(ThreadTree parent, ThreadTree child) { parent->rchild = child; if (child) child->parent = parent; } int main() { // 二叉树:A 为根;左子 B,右子 C;B 的左子 D、右子 E;C 的右子 F ThreadTree A = newNode('A'); ThreadTree B = newNode('B'); ThreadTree C = newNode('C'); ThreadTree D = newNode('D'); ThreadTree E = newNode('E'); ThreadTree F = newNode('F'); linkLeft(A, B); // A的左孩子=B linkRight(A, C); // A的右孩子=C linkLeft(B, D); // B的左子=D linkRight(B, E); // B的右子=E linkRight(C, F); // C的右子=F CreatePreThread(A); // 先序线索化 printf("先序的后继序列: "); PrintPreOrderNext(A); printf("先序的前驱序列: "); PrintPreOrderPrev(A); return 0; }
//后序线索二叉树 #include<stdio.h> #include<stdlib.h> #include<stdbool.h> typedef struct ThreadNode{ char data; struct ThreadNode *lchild, *rchild; int ltag, rtag; //左、右线索标记 }ThreadNode, *ThreadTree;//全局变量pre, 指向当前访问结点的前驱 ThreadTree pre=NULL; //建立前驱线索和后继线索 void visit(ThreadTree q){ if(q->lchild==NULL){ q->lchild=pre; //建立当前结点的前驱线索 q->ltag=1; } if(pre!=NULL && pre->rchild==NULL){ pre->rchild=q; //建立前驱结点的后继线索 pre->rtag=1; } pre=q; } //后序线索化二叉树 void PostThread(ThreadTree T){ if(T==NULL) return; PostThread(T->lchild); //后序遍历左子树 PostThread(T->rchild); //后序遍历右子树 visit(T); //访问根节点 } //建立后序线索二叉树 void CreatePostThread(ThreadTree T){ PostThread(T); //后序线索化二叉树 } //找到以p为根的子树中,最后一个被后序遍历的结点 ThreadTree LastNode(ThreadTree p){ return p; } //在后序线索二叉树中找到结点p的前驱结点 ThreadTree PreNode(ThreadTree p){ if(p->rtag==0) //若p有右子树 return p->rchild; else return p->lchild; } //输出前驱序列 void PostOrderPre(ThreadTree T){ for(ThreadTree p=LastNode(T); p!=NULL; p=PreNode(p)) printf("%c",p->data); } //先序递归构建二叉树 int sc=0; //全局变量sc, 枚举串 ThreadTree BuildBiTree(char *s){ //s为先序遍历串 ThreadTree T; if(s[sc]=='^') T=NULL; else{ T=(ThreadTree)malloc(sizeof(ThreadNode)); T->data=s[sc++]; T->lchild=BuildBiTree(s); sc++; T->rchild=BuildBiTree(s); } return T; } int main(){ char s[]="ABD^G^^E^^CF^^^"; ThreadTree T=BuildBiTree(s); //先序递归构建二叉树 CreatePostThread(T); //建立后序线索二叉树 PostOrderPre(T); //输出前驱序列 return 0; }
.
浙公网安备 33010602011771号