C语言实现二叉树的中序线索化及遍历中序线索二叉树

C语言实现二叉树的线索化以及如何遍历线索二叉树!


线索二叉树的结构及数据类型定义

//定义数据类型
typedef char ElemType;

//枚举,Link为0表示不是线索,Thread为1表示为线索
typedef enum {
    Link,
    Thread
} PointerTag;
//结点结构构造
typedef struct BiThrNode {
    ElemType data;//数据域
    struct BiThrNode *lchild, *rchild;//左右孩子指针域
    PointerTag Ltag, Rtag;//标志域,枚举类型
} BiThrNode, *BiThrTree;

BiThrTree pre = NULL;

根据输入结点初始化二叉树

//根据输入结点初始化并建立二叉树
bool CreateBiThrTree(BiThrTree &T) {
    //输入二叉树中的结点的值(一个字符),空格字符表示空树并构造二叉链表表示的树T
    ElemType ch;
    scanf("%c", &ch);
    getchar();
    if (ch == ' ') {
        T = NULL;
    } else {
        if (!(T = (BiThrTree) malloc(sizeof(BiThrNode)))) {
            return false;
        }
        T->data = ch;                    //生成根结点
        printf("请输入%c的左子树:", ch);
        CreateBiThrTree(T->lchild);        //构造左子树
        printf("请输入%c的右子树:", ch);
        CreateBiThrTree(T->rchild);        //构造右子树
    }
    return true;
}

中序遍历二叉树并线索化

//中序遍历并线索化
void InOrderThreading(BiThrTree T) {
    //如果当前结点没有左孩子,左标志位设为1,左指针域指向上一结点 pre
    if (!T->lchild) {
        T->Ltag = Thread;
        T->lchild = pre;
    }
    //如果 pre 没有右孩子,右标志位设为 1,右指针域指向当前结点。
    if (pre && !pre->rchild) {
        pre->Rtag = Thread;
        pre->rchild = T;
    }
    //pre指向当前结点
    pre = T;
}

//中序遍历二叉树并进行线索化
void InOrder(BiThrTree T) {
    //如果当前结点存在
    if (T) {
        InOrder(T->lchild);//递归当前结点的左子树,进行线索化
        Visit(T);
        InOrderThreading(T);
        InOrder(T->rchild);//递归右子树进行线索化
    }
}

遍历中序线索二叉树

//中序遍历线索二叉树
void InOrderThraverse_Thr(BiThrTree T) {
    while (T) {
        //一直找他的左孩子,查看Ltag是否为Thread(线索),即找到的最后一个为中序序列中排第一的
        while (T->Ltag == Link) {
            T = T->lchild;
        }
        Visit(T);  //操作结点数据
        //当结点右标志位为1时,直接找到其后继结点
        while (T->Rtag == Thread && T->rchild != NULL) {
            T = T->rchild;
            Visit(T);
        }
        //否则,按照中序遍历的规律,找其右子树中最左下的结点,也就是继续循环遍历
        T = T->rchild;
    }
}

项目完整代码

//中序遍历线索二叉树的实现
#include <stdio.h>
#include <stdlib.h>

//定义数据类型
typedef char ElemType;

//枚举,Link为0表示不是线索,Thread为1表示为线索
typedef enum {
    Link,
    Thread
} PointerTag;
//结点结构构造
typedef struct BiThrNode {
    ElemType data;//数据域
    struct BiThrNode *lchild, *rchild;//左右孩子指针域
    PointerTag Ltag, Rtag;//标志域,枚举类型
} BiThrNode, *BiThrTree;

BiThrTree pre = NULL;

//根据输入结点初始化并建立二叉树
bool CreateBiThrTree(BiThrTree &T) {
    //输入二叉树中的结点的值(一个字符),空格字符表示空树并构造二叉链表表示的树T
    ElemType ch;
    scanf("%c", &ch);
    getchar();
    if (ch == ' ') {
        T = NULL;
    } else {
        if (!(T = (BiThrTree) malloc(sizeof(BiThrNode)))) {
            return false;
        }
        T->data = ch;                    //生成根结点
        printf("请输入%c的左子树:", ch);
        CreateBiThrTree(T->lchild);        //构造左子树
        printf("请输入%c的右子树:", ch);
        CreateBiThrTree(T->rchild);        //构造右子树
    }
    return true;
}

//访问输出的Visit函数
void Visit(BiThrTree T) {    //输出元素的值
    printf("%c ", T->data);
}

//中序遍历线索化
void InOrderThreading(BiThrTree T) {
    //如果当前结点没有左孩子,左标志位设为1,左指针域指向上一结点 pre
    if (!T->lchild) {
        T->Ltag = Thread;
        T->lchild = pre;
    }
    //如果 pre 没有右孩子,右标志位设为 1,右指针域指向当前结点。
    if (pre && !pre->rchild) {
        pre->Rtag = Thread;
        pre->rchild = T;
    }
    //pre指向当前结点
    pre = T;
}

//中序遍历二叉树并进行线索化
void InOrder(BiThrTree T) {
    //如果当前结点存在
    if (T) {
        InOrder(T->lchild);//递归当前结点的左子树,进行线索化
        Visit(T);
        InOrderThreading(T);
        InOrder(T->rchild);//递归右子树进行线索化
    }
}

//中序遍历线索二叉树
void InOrderThraverse_Thr(BiThrTree T) {
    while (T) {
        //一直找他的左孩子,查看Ltag是否为Thread(线索),即找到的最后一个为中序序列中排第一的
        while (T->Ltag == Link) {
            T = T->lchild;
        }
        Visit(T);  //操作结点数据
        //当结点右标志位为1时,直接找到其后继结点
        while (T->Rtag == Thread && T->rchild != NULL) {
            T = T->rchild;
            Visit(T);
        }
        //否则,按照中序遍历的规律,找其右子树中最左下的结点,也就是继续循环遍历
        T = T->rchild;
    }
}

int main() {
    BiThrTree T;
    printf("请先输入树根结点(空格代表空结点):");
    CreateBiThrTree(T);
    printf("直接中序遍历二叉树的结果为:");
    InOrder(T);
    printf("\n");
    printf("遍历中序线索二叉树的结果为:");
    InOrderThraverse_Thr(T);
    printf("\n");
    return 0;
}

项目完整代码(改进版)

//中序遍历线索二叉树的实现(改进)
#include <stdio.h>
#include <stdlib.h>

//定义数据类型
typedef char ElemType;

//枚举,Link为0表示不是线索,Thread为1表示为线索
typedef enum {
    Link,
    Thread
} PointerTag;
//结点结构构造
typedef struct BiThrNode {
    ElemType data;//数据域
    struct BiThrNode *lchild, *rchild;//左右孩子指针域
    PointerTag Ltag, Rtag;//标志域,枚举类型
} BiThrNode, *BiThrTree;

BiThrTree pre = NULL;

//根据输入结点初始化并建立二叉树
bool CreateBiThrTree(BiThrTree &T) {
    //输入二叉树中的结点的值(一个字符),空格字符表示空树并构造二叉链表表示的树T
    ElemType ch;
    scanf("%c", &ch);
    getchar();
    if (ch == ' ') {
        T = NULL;
    } else {
        if (!(T = (BiThrTree) malloc(sizeof(BiThrNode)))) {
            return false;
        }
        T->data = ch;                    //生成根结点
        printf("请输入%c的左子树:", ch);
        CreateBiThrTree(T->lchild);        //构造左子树
        printf("请输入%c的右子树:", ch);
        CreateBiThrTree(T->rchild);        //构造右子树
    }
    return true;
}

//访问输出的Visit函数
void Visit(BiThrTree T) {    //输出元素的值
    printf("%c ", T->data);
}

//线索化函数
void OrderThreading(BiThrTree &T) {
    //如果当前结点没有左孩子,左标志位设为1,左指针域指向上一结点 pre
    if (!T->lchild) {
        T->Ltag = Thread;
        T->lchild = pre;
    }
    //如果 pre 没有右孩子,右标志位设为 1,右指针域指向当前结点。
    if (pre && !pre->rchild) {
        pre->Rtag = Thread;
        pre->rchild = T;
    }
    //pre指向当前结点
    pre = T;
}

//中序遍历二叉树
void InOrder(BiThrTree T) {
    //如果当前结点存在(左根右)
    if (T) {
        InOrder(T->lchild);     //递归当前结点的左子树
        Visit(T);
        OrderThreading(T);   //进行线索化
        InOrder(T->rchild);     //递归右子树进行线索化
    }
}

//中序遍历线索二叉树
void InOrderThraverse_Thr(BiThrTree T) {
    while (T) {
        //一直找他的左孩子,查看Ltag是否为Thread(线索),即找到的最后一个为中序序列中排第一的
        while (T->Ltag == Link) {
            T = T->lchild;
        }
        Visit(T);  //操作结点数据
        //当结点右标志位为1时,直接找到其后继结点
        while (T->Rtag == Thread && T->rchild != NULL) {
            T = T->rchild;
            Visit(T);
        }
        //否则,按照中序遍历的规律,找其右子树中最左下的结点,也就是继续循环遍历
        T = T->rchild;
    }
}

//中序遍历——找到以P为根结点的子树中,最后一个被中序遍历的
BiThrNode *InLastNode(BiThrNode *p) {
    //循环找到最右下的结点(不一定为叶子结点)
    while (p->Rtag == Link)
        p = p->rchild;
    return p;
}

//在中序线索二叉树中找到结点P的前驱结点
BiThrNode *InPreNode(BiThrNode *p) {
    //循环找到最右下的结点(不一定为叶子结点)
    if (p->Ltag == Link)
        return InLastNode(p->lchild);
    else
        return p->lchild;
}

//对中序线索二叉树进行逆向中序遍历
void ReInOderThraverse_Thr(BiThrNode *T) {
    for (BiThrNode *p = InLastNode(T); p != NULL; p = InPreNode(p)) {
        Visit(p);
    }
}

//线索二叉树T
void CreatThread(BiThrTree T) {
    if (T) {
        InOrder(T);
        if (!pre->rchild)
            pre->Rtag = Thread;
    }
}

int main() {
    BiThrTree T;
    printf("请先输入树根结点(空格代表空结点):");
    CreateBiThrTree(T);
    printf("\n");
    printf("直接中序遍历二叉树的结果为:");
    CreatThread(T);
    printf("\n\n");
    printf("正向遍历中序线索二叉树请输入  1\n");
    printf("逆向遍历中序线索二叉树请输入  2\n");
    printf("请选择是采用正向还是逆向输出:");
    int id;
    scanf("%d", &id);
    if (id == 1) {
        printf("正向遍历中序线索二叉树的结果为:");
        InOrderThraverse_Thr(T);
    }
    if (id == 2) {
        printf("逆向遍历中序线索二叉树的结果为:");
        ReInOderThraverse_Thr(T);
    }
    printf("\n");
    return 0;
}

运行效果图

在这里插入图片描述

在这里插入图片描述

  • 31
    点赞
  • 169
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
好的,我知道你想让我用C语言实现二叉树的前序遍历中序遍历和后序遍历。下面是相应的代码: 首先,我们需要定义二叉树的节点结构: ``` typedef struct node{ int data; struct node *left; struct node *right; }Node; ``` 接下来,我们可以编写代码来创建节点: ``` Node* createNode(int data) { Node* newNode = (Node*)malloc(sizeof(Node)); newNode->data = data; newNode->left = NULL; newNode->right = NULL; return newNode; } ``` 对于二叉树的前序遍历,我们需要按照“根节点-左子树-右子树”的顺序来遍历二叉树。以下是前序遍历的代码: ``` void preOrderTraversal(Node* root) { if(root != NULL) { printf("%d ",root->data); preOrderTraversal(root->left); preOrderTraversal(root->right); } } ``` 对于二叉树中序遍历,我们需要按照“左子树-根节点-右子树”的顺序来遍历二叉树。以下是中序遍历的代码: ``` void inOrderTraversal(Node* root) { if(root != NULL) { inOrderTraversal(root->left); printf("%d ",root->data); inOrderTraversal(root->right); } } ``` 对于二叉树的后序遍历,我们需要按照“左子树-右子树-根节点”的顺序来遍历二叉树。以下是后序遍历的代码: ``` void postOrderTraversal(Node* root) { if(root != NULL) { postOrderTraversal(root->left); postOrderTraversal(root->right); printf("%d ",root->data); } } ``` 这就是用C语言实现二叉树的前序遍历中序遍历和后序遍历的代码。希望能对你有所帮助。如果你还有其他问题,欢迎继续向我提问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值