先序,中序,后序线索化二叉树

本文介绍了一种基于先序、中序和后序遍历的二叉树线索化实现方法,并提供了完整的C++代码示例。通过加入头结点实现了二叉树的线索化过程,包括求结点的前驱和后继结点等操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本文是作者整理网上代码得到!
输入先序序列:ABDH##I##EJ###CF##G##

#include <stdio.h>
#include <malloc.h>
#include <iostream>
#define max 100

using namespace std;

typedef char datatype;
typedef enum PointerTag { Link, Thread };
struct node
{
    struct node *lchild;
    struct node *rchild;
    datatype data;
    //int level;//层级
    PointerTag ltag;
    PointerTag rtag;
};
typedef struct node *BTREE;


void CreateBT(BTREE &T)//建树,按先序顺序输入节点
{
    char ch;
    scanf_s("%c", &ch);
    if (ch == '#')
    {
        T = NULL;
        return;
    }
    else
    {
        T = (BTREE)malloc(sizeof(node));
        if (!T)
            exit(1);
        T->data = ch;
        T->ltag = Link;
        T->rtag = Link;
        CreateBT(T->lchild);
        CreateBT(T->rchild);
    }
}

BTREE pre = (node*)malloc(sizeof(node));
//实现二叉链表的先序线索化;
void PreThreading(BTREE P) {
    if (P) {

        if (!P->lchild) {
            P->ltag = Thread;
            P->lchild = pre;
        }
        else P->ltag = Link;

        if (!pre->rchild) {
            pre->rtag = Thread;
            pre->rchild = P;
        }
        else P->rtag = Link;

        pre = P;
        if (Link == P->ltag)
            PreThreading(P->lchild);
        if (Link == P->rtag)
            PreThreading(P->rchild);
    }
}

//加入头结点,先序线索二叉树
void PreOrderThread_Head(BTREE &head, BTREE &P) {
    head = (node*)malloc(sizeof(BTREE));
    head->rchild = head;//右指针回指
    head->ltag = Link;
    head->rtag = Thread;//建立头结点
    if (!P) {
        head->lchild = head;//空树
    }
    else {
        head->lchild = P;
        pre = head;
        PreThreading(P);//先序遍历进行先序线索化
        pre->rtag = Thread;
        pre->rchild = head;
        head->rchild = pre;
    }
}
//求先序线索二叉树中结点p 的先序顺序的后继结点p*
BTREE PreNext(BTREE p)
{
    BTREE q;
    if (p->ltag == Link) q = p->lchild;
    else  q = p->rchild;
    return q;
}
//实现先序线索链表的先序遍历。
void ForOrderTraverse_Thr(BTREE T) {
    BTREE p = T->lchild;
    while (p != T)
    {
        printf("%c", p->data);
        p = PreNext(p);
    }
}
//----------------------------------------------------------------------------------------------------------------------------
//实现二叉链表的中序线索化;
void InThreading(BTREE P) {
    if (P) {
        InThreading(P->lchild);
        if (!P->lchild) {
            P->ltag = Thread;
            P->lchild = pre;
        }
        else P->ltag = Link;

        if (!pre->rchild) {
            pre->rtag = Thread;
            pre->rchild = P;
        }
        else P->rtag = Link;
        pre = P;
        InThreading(P->rchild);
    }
}
//加入头结点,中序线索二叉树
void InOrderThread_Head(BTREE &head, BTREE &P) {
    head = (node*)malloc(sizeof(BTREE));
    head->rchild = head;//右指针回指
    head->ltag = Link;
    head->rtag = Thread;//建立头结点
    if (!P) {
        head->lchild = head;//空树
    }
    else {
        head->lchild = P;
        pre = head;
        InThreading(P);//中序遍历进行中序线索化
        pre->rtag = Thread;
        pre->rchild = head;
        head->rchild = pre;
    }
}
//在中序线索二叉树中求一个结点p的中序后继p$
BTREE InNext(BTREE p)
{
    BTREE q;
    if (p->rtag == Thread)
    {
        q = p->rchild;
    }
    else
    {
        q = p->rchild;
        while (q->ltag == Link) q = q->lchild;//右子树的最左节点
    }
    return q;
}
//实现中序线索链表的中序遍历。
void InOrderTraverse_Thr(BTREE T) {
    BTREE p = T->lchild;

    while (p->ltag == Link)
    {
        p = p->lchild;
    }
    while (p != T)
    {
        printf("%c", p->data);
        p = InNext(p);
    }
}
//-------------------------------------------------------------------------------------------------------------------------------------

//实现二叉链表的后序线索化;
void PostThreading(BTREE P) {
    if (P) {
        if (Link == P->ltag)
            PostThreading(P->lchild);
        if (Link == P->rtag)
            PostThreading(P->rchild);

        if (!P->lchild) {
            P->ltag = Thread;
            P->lchild = pre;
        }
        else P->ltag = Link;

        if (!pre->rchild) {
            pre->rtag = Thread;
            pre->rchild = P;
        }
        else P->rtag = Link;
        pre = P;

    }
}
//加入头结点,后序线索二叉树
void PostOrderThread_Head(BTREE &head, BTREE &P) {
    head = (node*)malloc(sizeof(BTREE));
    head->rchild = head;//右指针回指
    head->ltag = Link;
    head->rtag = Thread;//建立头结点
    if (!P) {
        head->lchild = head;//空树
    }
    else {
        head->lchild = P;
        pre = head;
        PostThreading(P);//后序遍历进行后序线索化
        head->rchild = pre;
    }
}
//在后序线索二叉树中求一个结点p的父节点
BTREE parent(BTREE &T, BTREE    &p)
{
    BTREE    temp;
    temp = T;
    if (temp->lchild == p)
        return temp;    //父节点是头结点
    else
    {
        temp = temp->lchild;
        while (temp->lchild != p && temp->rchild != p)
        {
            if (Link == temp->rtag)
                temp = temp->rchild;    //如果节点有右节点,那么往右
            else
                temp = temp->lchild;    //如果节点没有右孩子,那么去左孩子,没有左孩子,去前驱,也是走往左
        }
        return temp;
    }
}
//求后序线索二叉树中结点p 的后序顺序的后继结点p*
BTREE PostNext(BTREE &T,BTREE &p)
{
    BTREE par;
    par = parent(T, p);    //parent是p的双亲:
    if (T == par)    return T;    //1.若parent是T,即p是根节点,则无后继
    else if (p == par->rchild || Thread == par->rtag)    //2.若p是双亲的右孩子,或者是独生左孩子,则后继为双亲
        return par;
    else
    {
        while (par->rtag == Link)        //3.若p是有兄弟的左孩子,则后继为双亲的右子树上按照后续遍历访问的第一个节点。
        {
            par = par->rchild;
            while (par->ltag == Link)
            {
                par = par->lchild;
            }
        }
        return par;
    }   
}
//实现后序线索链表的后序遍历。
void PostOrderTraverse_Thr(BTREE T) {
    BTREE p = T->lchild;
    while (1)
    {
        while (Link == p->ltag)     p = p->lchild;
        if (Link == p->rtag)    p = p->rchild;
        else    break;        //p指向第一个被访问的节点
    }
    while (p != T)
    {
        printf("%c", p->data);
        p = PostNext(T,p);
    }
}


int  main()
{
    BTREE a, s;
    pre->rtag = Thread;
    pre->rchild = NULL;
    printf("先序建立二叉链表,请输入: ");
    CreateBT(a);
    int i;
    printf("输入1先序线索化,输入2中序线索化,输入3后序线索化: ");
    scanf_s("%d", &i);
    getchar();
    if (i == 1) {
        printf("先序线索化ing\n");
        PreOrderThread_Head(s, a);

        printf("先序线索化后先序输出此树:");
        ForOrderTraverse_Thr(s); printf("\n");
    }
    else if (i == 2)
    {
        printf("中序线索化ing\n");
        InOrderThread_Head(s, a);

        printf("中序线索化后先序输出此树:");
        InOrderTraverse_Thr(s); printf("\n");
    }
    else {
        printf("后序线索化ing\n");
        PostOrderThread_Head(s, a);

        printf("后序线索化后先序输出此树:");
        PostOrderTraverse_Thr(s); printf("\n");
    }

    system("pause");
    return 0;
}

输出:


评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值