线索化二叉树及其基本方法实现

线索化二叉树的初始化

  • 线索化二叉树是根据中序遍历产生的,当一个左右子树节点为空时,使其左子树指向其前驱节点,右子树指向其后继结点
  • 为了区分指针到底指向的是前驱后继节点还是左右子树,需要在创建树的节点时再创建两个空间分别用来标记其左右指针指的是什么
typedef   enum{LINK,THREAD}TAG;
typedef struct node
{
    char data;
    struct node*lchild;
    struct node*rchild;
    TAG rtag;
    TAG ltag;
}*PNODE,NODE;
typedef struct tree
{
    PNODE root;
    char ref;
}TREE;
PNODE create(TREE*t);
void init(TREE* t);
void fronttraverse(PNODE root);
void thread(PNODE t,PNODE *pre);
PNODE first(PNODE root);
PNODE last(PNODE root);
PNODE prio(TREE*t,PNODE cur);
PNODE next(TREE*t,PNODE cur);
void traverse(TREE*t);
int main()
{
    TREE tree;PNODE pre=NULL;
    init(&tree);
    (&tree)->root=create(&tree);
    thread((&tree)->root,&pre);
    pre->rchild=NULL;

    pre->rtag=THREAD;

    traverse(&tree);
}
void init(TREE* t)
{
    t->root=NULL;
    t->ref='#';
}

线索化二叉树的创建

  • 需要先按二叉树的创建方法将树结构创建出来,再将其进行线索化
  • 线索化是按中序遍历进行的,因此需要按中序的顺序找到最左下的树
PNODE create(TREE*t)//ABC##DE##F##G#H##
{
    char item;
    scanf("%c",&item);
    if(t->ref==item)
    return NULL;
    else{
        PNODE p=(PNODE)malloc(sizeof(NODE));
        p->data=item;
        p->rtag=LINK;
        p->ltag=LINK;
        p->lchild=create(t);
        p->rchild=create(t);
        return p;
}
    }
void thread(PNODE t,PNODE*pre)//先找到最左的子树,然后判断其左子树是否为空,贴上标记,pre=NULL,
//因为是中序遍历,所以最左下的子树是没有前驱结点的,然后返回上一个节点,pre=t,连接最左下子树于t,最左下树的后继结点就是t
{
    if(t==NULL)return;

    thread(t->lchild,pre);
    if(t->lchild==NULL)
    {
        t->ltag=THREAD;
        t->lchild=(*pre);
    }

    if((*pre)!=NULL&&(*pre)->rchild==NULL)
    {
        (*pre)->rtag=THREAD;
        (*pre)->rchild=t;
    }
    (*pre)=t;
    thread(t->rchild,pre);

}

线索化二叉树的方法实现

1.找寻中序遍历下的第一个元素
PNODE first(PNODE root)//从根节点向左下寻找知道树的Tag不为LINK,而是THREAD
{
    PNODE p=root;
    while(p->ltag==LINK)
    {
        p=p->lchild;
    }
    return p;
}
2.找寻中序遍历下的最后一个元素
PNODE last(PNODE root)//根据中序遍历规则,中序的最后一个节点是最右下的节点,因此向右子树遍历即可
{
    PNODE p=root;
    while(p->rtag==LINK)
    {
        p=p->rchild;
    }
    return p;
}
3.找寻一个节点的在中序下的前驱节点
PNODE prio(TREE*t,PNODE cur)
{
    if(t==NULL||cur==NULL)
        return NULL;
    if(cur->ltag==THREAD)//如果刚好是线索点,则它的前驱节点就是它的左子树
    {
        return cur->lchild;
    }
    return last(cur->lchild);//如果不是,由于是中序遍历,因此节点的前驱节点是其左子树中的最后一个
}
4.找寻一个节点在中序下的后继结点
PNODE next(TREE*t,PNODE cur)
{
    if(t==NULL||cur==NULL)
        return NULL;
    if(cur->rtag==THREAD)//如果是线索节点,则它的后继结点就是它的右子树
    {
        return cur->rchild;
    }
    return first(cur->rchild);//如果不是,由于是中序遍历,因此节点的后继结点是其右子树中的第一个
}
5.遍历线索化二叉树
void traverse(TREE*t)
{
    for(PNODE p=first(t->root);p!=NULL;p=next(t,p))
    {

        printf("%c ",p->data);
    }
    printf("\n");
}
6.查找某个值并返回其节点
PNODE search(TREE*t,char key)
{
    for(PNODE p=first(t->root);p!=NULL;p=next(t,p))//将其遍历得到节点
    {
        if(p->data==key)
            return p;
    }
}
7.找到一个结点的父节点
PNODE parent(TREE*t,PNODE cur)//共有四种情况找寻其父节点
{
    if(t==NULL||cur==NULL)
        return NULL
    PNODE p;
    if(cur->ltag==THREAD)//如果是线索节点看看它的前驱结点是不是它的父节点
    {
        p=cur->lchild;
        if(p->rchild==cur)
            return p;
    }
    if(cur->rtag==THREAD)//如果是线索节点看看他的后继结点是不是它的父节点
    {
        p=cur->rchild;
        if(p->lchild==cur)
            return p;
    }
    p=first(cur->lchild);//如果不是线索节点,看看它左孩子中的第一个节点是不是它的父节点;或者他的右孩子中最后一个节点是不是它的父节点
    p=p->lchild;
    if(p!=NULL&&p->rchild==cur)
        return p;
    p=last(cur->rchild);
    return p->rchild;
}
总结
  • 线索化是对中序、前序、后序遍历而言的,它按这种遍历方式将二叉树存储,可以很方便的找到这种遍历方式下的前驱节点或者后继结点
  • 而在遍历二叉树时,也像遍历数组一样用for循环遍历即可,不需要再使用递归了
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值