线索二叉树(附栈)---创造、前序、对称序周游,寻找指定元素前驱

线索二叉树(附栈)—创造、前序、对称序周游,寻找指定元素前驱

```javascript
#include <stdio.h>
#include <malloc.h>



/*---------------线索二叉树----------------*/
struct ThrTreeNode;  //线索二叉树的节点
typedef struct ThrTreeNode* P_ThrTree; //节点中的指针类型
struct ThrTreeNode{  //线索二叉树节点的定义
    char data;    //数据
    P_ThrTree L_link,R_link; //子树的指针
    int ltag,rtag;  //是否为线索型指针的标记
}; //线索二叉树定义
typedef struct ThrTreeNode* ThrTree;  //线索二叉树类型
/*---------------线索二叉树----------------*/



/*---------------栈----------------*/
struct SeqStack{
    int MAXNUM;  //栈中最大存储数量
    int t;   //栈顶元素位置
    ThrTree *s;  //树节点栈
};
typedef struct SeqStack* PSeqStack;
/*---------------栈----------------*/

/*---------------栈的方法----------------*/
//栈:创建栈
PSeqStack create_NULL_Stack(int m){
    PSeqStack stack = (PSeqStack)malloc(sizeof(struct SeqStack));
    if(stack!=NULL)
    {
        stack->s = (ThrTree*)malloc(sizeof(ThrTree)*m);
        if(stack->s)
        {
            stack->MAXNUM = m;
            stack->t = -1;
            return stack;
        }else{
            free(stack);
        }
    }
    printf("创建失败\n");
    return NULL;
}
//栈:进栈
void push_seq(PSeqStack pastack,ThrTree x){
    if(pastack->t>=pastack->MAXNUM-1)
    {
        printf("超出栈存储范围!\n");
        return;
    }
    else
    {
        pastack->t = pastack->t + 1;
        pastack->s[pastack->t] = x;
        return;
    }
}
//栈:出栈
void pop_seq(PSeqStack pastack){
    if(pastack->t==-1)
    {
        printf("出栈,栈是空的!\n");
        return;
    }
    else
    {
        pastack->t = pastack->t - 1;
    }
}
//栈:取栈顶元素
ThrTree top_seq(PSeqStack pastack){
    if(pastack->t==-1)
    {
        printf("取栈顶,栈是空的!\n");
    }
    else
    {
        return(pastack->s[pastack->t]); //返回栈顶元素
    }
}
//栈:判断空栈
int isEmptyStack_seq(PSeqStack pastack){
    if(pastack->t==-1)
    {
        return 1;
    }
    else
    {
        return 0;
    }
}
/*---------------栈的方法----------------*/







/*---------------线索二叉树的方法----------------*/
//线索二叉树:创建
ThrTree create_ThrTree(P_ThrTree thrTree){
    printf("输入该节点的字符:(输入:#返回上一级)\n");
    char ch;
    scanf("%c",&ch);
    getchar();
    if(ch=='#')
    {
        printf("#  返回上一级\n");
        return NULL ;
    }
    else
    {
        thrTree = (ThrTree)malloc(sizeof(struct ThrTreeNode));
        ThrTree Pointer = thrTree;
        Pointer->data = ch;
        Pointer->ltag = 0;
        Pointer->rtag = 0;
        Pointer->L_link = NULL;
        Pointer->R_link = NULL;
        printf("创建<--左子树\n");
        Pointer->L_link = create_ThrTree(Pointer->L_link);
        printf("创建右子树-->\n");
        Pointer->R_link = create_ThrTree(Pointer->R_link);
    }
    return thrTree;
}
//线索二叉树:求树高
int getHeight_tree(ThrTree thrTree){
    int left_height,right_height,theHeight;
    if(thrTree!=NULL)
    {
        left_height = getHeight_tree(thrTree->L_link);
        right_height = getHeight_tree(thrTree->R_link);
        theHeight = left_height > right_height ? left_height : right_height;
        return theHeight+1;
    }else{
        return 0;
    }
}
//线索二叉树:线索化
void thread(ThrTree thrTree){
    //新建一个栈,栈的大小一般取树高
    PSeqStack st = create_NULL_Stack(getHeight_tree(thrTree));
    ThrTree p,pr;//分别指向前驱、本节点
    p = thrTree;
    pr = NULL; //这样初始赋值,有利于pr节点就位
    do{
        //从主根开始,将向左寻找极左时遇见的节点全部压到栈中
        while(p!=NULL)
        {
            push_seq(st,p);
            p = p->L_link;
        }
        p = top_seq(st);//让目前的节点等于栈顶
        pop_seq(st);//退出栈
        printf("当前栈定元素的标号为:%d\n",st->t);
        if(pr!=NULL)//当前驱节点就位时
        {
            //前驱节点的右子树如果为空,则修改

            if(pr->R_link==NULL)
            {
                printf("pr前驱节点:%c,可以修改:右子树(指向后继:%c)\n",pr->data,p->data);
                pr->R_link = p;
                pr->rtag = 1;
            }
            //本节点的左子树如果为空,则修改

            if(p->L_link==NULL)
            {
                printf("p当前节点:%c,可以修改:左子树(指向前驱:%c)\n",p->data,pr->data);
                p->L_link = pr;
                p->ltag = 1;
            }
        }
        //如果前驱节点未就位,则前驱节点等于当前节点,当前节点进入右子树去探寻下一个“极左”
        pr = p;
        p = p->R_link;
    }while(!isEmptyStack_seq(st)||p!=NULL);//栈不空或p不指向NULL时(当回到主根,栈空而p指向mainroot),可以进行循环
}
//线索二叉树:先根次序周游
void preOrder(ThrTree thrTree){
    if(thrTree==NULL)
    {
        return;
    }
    printf("%c\n",thrTree->data);
    printf("-----------------------------");
    preOrder(thrTree->L_link);
    preOrder(thrTree->R_link);
}
//线索二叉树:对称序列周游
void inOrder(ThrTree thrTree){
    ThrTree pointer = thrTree;
    if(pointer==NULL)
    {
        return;
    }
    while(pointer->L_link!=NULL&&pointer->ltag==0)//不顺着线索,找到极左
    {
        pointer = pointer->L_link;
    }
    while(pointer!=NULL)
    {
        printf("%c",pointer->data);
        if(pointer->R_link!=NULL&&pointer->rtag==0)//当右子树不是线索时,顺着右子树的左子树继续找极左
        {
            pointer = pointer->R_link;
            while(pointer->L_link!=NULL&&pointer->ltag==0)
            {
                pointer = pointer->L_link;
            }
        }else{
            pointer = pointer->R_link;//右子树是线索,顺着线索访问
        }
    }
}
//线索二叉树:找到对称序列的前驱
void find_Pioneer(ThrTree thrTree,char x){
    ThrTree pointer = thrTree;
    ThrTree mark;
    if(pointer==NULL)
    {
        return;
    }
    while(pointer->L_link!=NULL&&pointer->ltag==0)//不顺着线索,找到极左
    {
        pointer = pointer->L_link;
    }
    while(pointer!=NULL)
    {
        if(pointer->data==x&&pointer->ltag==1) //目标节点是持有线索的节点,则前驱为左子树
        {
            printf("前驱为:%c\n",pointer->L_link->data);
        }else if(pointer->data==x&&pointer->ltag==0){ //目标节点不持有线索的节点,则前驱为有线索的一个节点
            printf("前驱为:%c\n",mark->data);
        }
        if(pointer->R_link!=NULL&&pointer->rtag==0)//当右子树不是线索时,顺着右子树的左子树继续找极左
        {
            pointer = pointer->R_link;
            while(pointer->L_link!=NULL&&pointer->ltag==0)
            {
                pointer = pointer->L_link;
            }
        }else{
            mark = pointer;
            pointer = pointer->R_link;//右子树是线索,顺着线索访问
        }
    }
}
/*---------------线索二叉树的方法----------------*/



int main() {
    ThrTree thrTree = create_ThrTree(thrTree);
    printf("树创建完成\n");
    printf("树高为:%d\n",getHeight_tree(thrTree));
    printf("周游树:先根序列\n");
    preOrder(thrTree);
    thread(thrTree);
    printf("线索化完成\n");
    /*
    printf("测试线索化:\n");
    ThrTree thrTreetest = thrTree;
    thrTreetest = thrTreetest->L_link;
    thrTreetest = thrTreetest->R_link;
    printf("当前为:%c,线索为:%c\n",thrTreetest->data,thrTreetest->R_link->data);
     */ //测试线索化
    printf("周游树:对称序列\n");
    inOrder(thrTree);
    while(1)
    {
        printf("输入你想找到其前驱的字符:\n");
        getchar();
        char x;
        scanf("%c",&x);
        find_Pioneer(thrTree,x);
    }
    return 0;
}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值