线索二叉树的基本操作

//定义数据类型
typedef enum{Link, Thread} PointerTag;      //link = 0表示指向左右孩子指针,Thread = 1表示指向前驱或后继的线索
typedef struct BitNode
{
    char data;                              //结点数据
    struct BitNode *lchild;                 //左右孩子指针
    struct BitNode *rchild;
    PointerTag ltag;                        //左右标志
    PointerTag rtag;
}BitNode, *BiTree;
 
BiTree pre;                                 //全局变量,始终指向刚刚访问过的结点
 
//前序创建二叉树
void CreateTree(BiTree T)
{
    char ch;
    scanf("%c", &ch);
    if(ch == '#')
    {
       T= NULL;
    }
    else
    {
        if(!T=(BiTree)malloc(sizeof(BitNode))) return 0;
        T->data = ch;
        CreateTree(T->lchild));
        CreateTree(T->rchild));
    }
    return 0;
}
 ----------------------------------------------------------------------------------------
 
中序遍历线索化,得到中序线索二叉树
//thr指向头结点,头结点左链lchild指向根结点,头结点右链rchild指向中序遍历的最后一个结点。
int InOrderThraverse_Thr(BiTree T)
{
    BiTree thr;
    thr->ltag=Link;
    thr-rtag=Thread;
    thr->rchild=thr;
    if(!T)
        thr-lchild=thr;
    else{
        pre=thr;
        InThreading(T);
        pre->rtag=Thread;
        pre->rchild=thr;
        thr->rchild=pre;
    }
    return OK;
}
 
//中序线索化
void InThreading(BiTree p)
{
    if(p)
    {
        InThreading(p->lchild);              //递归左子树线索化
 
        if(!p->lchild)                       //没有左孩子
        {
            p->ltag = Thread;                //前驱线索
            p->lchild = pre;             //左孩子指针指向前驱,这里是第3步
        }
        if(!pre->rchild)                 //没有右孩子
        {
            pre->rtag = Thread;              //后继线索
            pre->rchild = p;             //前驱右孩子指针指向后继(当前结点p)
        }
        pre=p;
 
        InThreading(p->rchild);              //递归右子树线索化
    }
}
----------------------------------------------------------------------------------------
//查找前驱节点及后继节点
 
在中序线索二叉树上查找任意结点的中序前驱结点
对于中序线索二叉树上的任一结点,寻找其中序的前驱结点,有以下两种情况:
 
(1)如果该结点的左标志为1,那么其左指针域所指向的结点便是它的前驱结点;
(2)如果该结点的左标志为0,表明该结点有左孩子,根据中序遍历的定义,它的前驱结点
     是以该结点的左孩子为根结点的子树的最右结点,即沿着其左子树的右指针链向下查找。
     当某结点的右标志为1 时,它就是所要找的前驱结点。
 
BiTree InPreNode(BiTree &p){
    BiTree pre;
    pre=p->lchild;
    if(!p->ltag)
        while(!pre->rtag){
            pre=pre->rchild;
        }
    }
    return pre;
}
 
 
//在中序线索二叉树上查找任意结点的中序后继结点
 
对于中序线索二叉树上的任一结点,寻找其中序的后继结点,有以下两种情况:
(1)如果该结点的右标志为1,那么其右指针域所指向的结点便是它的后继结点;
(2)如果该结点的右标志为0,表明该结点有右孩子,根据中序遍历的定义,它的前驱结点
     是以该结点的右孩子为根结点的子树的最左结点,即沿着其右子树的左指针链向下查找.
     当某结点的左标志为1 时,它就是所要找的后继结点。
 
BiTree InPostNode(BiTree &p){
    BiTree post;
    post=p->rchild;
    if(!p->rtag)
        while(!post->ltag){
            pre=pre->lchild;
        }
    }
    return post;
}
 
--------------------------------------------------------------------------------------
 
//在中序线索二叉树上查找值为x的结点(遍历线索二叉树)
 
    利用在中序线索二叉树上寻找后继结点和前驱结点的算法,就可以遍历到二叉树的所有结
点。比如,先找到按某序遍历的第一个结点,然后再依次查询其后继;或先找到按某序遍历的
最后一个结点,然后再依次查询其前驱。这样,既不用栈也不用递归就可以访问到二叉树的所
有节点。
 
   在中序线索二叉树上查找值为x 的结点,实质上就是在线索二叉树上进行遍历,将访问结点
的操作具体写为那结点的值与x 比较的语句。
 
BiTree Insearch(BiTree head,chare){
    BiTree p;
    p=head->lchild;
    while(p->ltag==0&&p!=head)      p=head为遍历结束标志
        p=p->lchild;                找到中序遍历的第一个节点(最左孩子)
    while(p->data!=e&&p!=head)      p=head为遍历结束标志
        InPostNode(p);
    if(p->data==e)
        return p;
    else{
        printf("没找到");
        return 0;
 }
 
-----------------------------------------------------------------------------------------
 
//在中序线索二叉树上的插入与删除
 
        线索二叉树的更新是指,在线索二叉树中插入一个结点或者删除一个结点。一般情况下,这些操作有
可能破坏原来已有的线索,因此,在修改指针时,还需要对线索做相应的修改。一般来说,这个过程的代
价几乎与重新进行线索化相同。这里仅讨论一种比较简单的情况,即在中序线索二叉树中插入一个结点p,
使它成为结点s 的右孩子。
 
下面分两种情况来分析:
 
(1)若s 的右子树为空,如图6.13 (a)所示,则插入结点p 之后成为图6.13 (b)所示的情形。在这种情况中,
     s 的后继将成为p 的中序后继,s 成为p 的中序前驱,而p 成为s 的右孩子。二叉树中其它部分的指针
     和线索不发生变化。
 
(2)若s 的右子树非空,如图6.14 (a)所示,插入结点p 之后如图6.14 (b)所示。S 原来的右子树变成p 的右
     子树,由于p 没有左子树,故s 成为p 的中序前驱,p 成为s 的右孩子;又由于s 原来的后继成为p 的后
     继,因此还要将s 原来的本来指向s 的后继的左线索,改为指向p。
 
 
下面给出上述操作的算法。
 
void InsertThrRight(BiThrTree s,BiThrTree p)
{
   
    BiThrTree w;
    p->rchild=s->rchild;
    p->rtag=s->rtag;
    p->lchild=s;
    p->ltag=1;
    s->rchild=p;
    s->rtag=0;
    if(p->rtag==0)
    {
        w=InPostNode(p);
        w->lchild=p;
    }
}

posted on 2016-05-07 00:56  yujon  阅读(1874)  评论(0编辑  收藏  举报

导航