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;
}
 

 

 

.

posted @ 2026-09-29 07:02  董晓  阅读(8)  评论(0)    收藏  举报