• 线索二叉树的基本操作


    //定义数据类型
    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;
        }
    }
  • 相关阅读:
    C#操作Windows控制面板
    WPF打印控件内容
    LINQ函数
    通过实现System.IComparable接口的CompareTo方法对两个类进行比较
    泛型和约束
    CSS样式基础总结
    C#调用百度高精度IP定位API通过IP获取地址
    软件下载路径
    RNN学习资料
    mysql 不能插入中文记录
  • 原文地址:https://www.cnblogs.com/yujon/p/5467598.html
Copyright © 2020-2023  润新知