美文网首页
数据结构与算法 线索二叉树

数据结构与算法 线索二叉树

作者: 今年27 | 来源:发表于2020-05-03 09:37 被阅读0次

    线索二叉树原理:
    在一个二叉树中,在不是完全二叉树的情况下,二叉树结点的左孩子或者右孩子存在为NULL的情况,我们可以将其利用起来,进行线索化。
    好处就是可以优化二叉树的利用空间

    #include "string.h"
    #include "stdio.h"
    #include "stdlib.h"
    
    #include "math.h"
    #include "time.h"
    
    #define OK 1
    #define ERROR 0
    #define TRUE 1
    #define FALSE 0
    #define MAXSIZE 100 /* 存储空间初始分配量 */
    
    /* Status是函数的类型,其值是函数结果状态代码,如OK等 */
    typedef int Status;
    typedef char CElemType;
    /* 字符型以空格符为空 */
    CElemType Nil='#';
    
    #pragma mark--二叉树构造
    int indexs = 1;
    typedef char String[24]; /*  0号单元存放串的长度 */
    String str;
    Status StrAssign(String T,char *chars)
    {
        int i;
        if(strlen(chars)>MAXSIZE)
            return ERROR;
        else
        {
            T[0]=strlen(chars);
            for(i=1;i<=T[0];i++)
                T[i]=*(chars+i-1);
            return OK;
        }
    }
    
    /* Link==0表示指向左右孩子指针, */
    /* Thread==1表示指向前驱或后继的线索 */
    typedef enum {Link,Thread} PointerTag;
    
    /* 线索二叉树存储结点结构*/
    typedef struct BiThrNode{
        
        //数据
        CElemType data;
        
        //左右孩子指针
        struct BiThrNode *lchild,*rchild;
        
        //左右标记
        PointerTag LTag;
        PointerTag RTag;
        
    }BiThrNode,*BiThrTree;
    
    /*
     8.1 打印
     */
    Status visit(CElemType e)
    {
        printf("%c ",e);
        return OK;
    }
    
    /*
     8.3 构造二叉树
     按照前序输入线索二叉树结点的值,构造二叉树T
     */
    
    Status CreateBiThrTree(BiThrTree *T){
        
        CElemType h;
        //scanf("%c",&h);
        //获取字符
        h = str[indexs++];
        
        if (h == Nil) {
            *T = NULL;
        }else{
            *T = (BiThrTree)malloc(sizeof(BiThrNode));
            if (!*T) {
                exit(OVERFLOW);
            }
            //生成根结点(前序)
            (*T)->data = h;
            
            //递归构造左子树
            CreateBiThrTree(&(*T)->lchild);
            //存在左孩子->将标记LTag设置为Link
            if ((*T)->lchild) (*T)->LTag = Link;
            
            //递归构造右子树
            CreateBiThrTree(&(*T)->rchild);
            //存在右孩子->将标记RTag设置为Link
            if ((*T)->rchild) (*T)->RTag = Link;
        }
        
        return OK;
    }
    
    
    /*
     8.3 中序遍历二叉树T, 将其中序线索化,Thrt指向头结点
     */
    
    BiThrTree pre; /* 全局变量,始终指向刚刚访问过的结点 */
    /* 中序遍历进行中序线索化*/
    void InThreading(BiThrTree p){
        
        /*
         InThreading(p->lchild);
         .....
         InThreading(p->rchild);
         */
        if (p) {
            //递归左子树线索化
            InThreading(p->lchild);
            //无左孩子
            if (!p->lchild) {
                //前驱线索
                p->LTag = Thread;
                //左孩子指针指向前驱
                p->lchild  = pre;
            }else
            {
                p->LTag = Link;
            }
            
            //前驱没有右孩子
            if (!pre->rchild) {
                //后继线索
                pre->RTag = Thread;
                //前驱右孩子指针指向后继(当前结点p)
                pre->rchild = p;
            }else
            {
                pre->RTag = Link;
            }
            
            //保持pre指向p的前驱
            pre = p;
            //递归右子树线索化
            InThreading(p->rchild);
        }
    }
    
    /* 中序遍历二叉树T,并将其中序线索化,Thrt指向头结点 */
    Status InOrderThreading(BiThrTree *Thrt , BiThrTree T){
        
        *Thrt=(BiThrTree)malloc(sizeof(BiThrNode));
        
        if (! *Thrt) {
            exit(OVERFLOW);
        }
        
        //建立头结点;
        (*Thrt)->LTag = Link;
        (*Thrt)->RTag = Thread;
        //右指针回指向
        (*Thrt)->rchild = (*Thrt);
        
        /* 若二叉树空,则左指针回指 */
        if (!T) {
            (*Thrt)->lchild=*Thrt;
        }else{
            
            (*Thrt)->lchild=T;
            pre=(*Thrt);
            
            //中序遍历进行中序线索化
            InThreading(T);
            
            //最后一个结点rchil 孩子
            pre->rchild = *Thrt;
            //最后一个结点线索化
            pre->RTag = Thread;
            (*Thrt)->rchild = pre;
            
        }
        return OK;
    }
    
    /*中序遍历二叉线索树T*/
    Status InOrderTraverse_Thr(BiThrTree T){
        BiThrTree p;
        p=T->lchild; /* p指向根结点 */
        while(p!=T)
        { /* 空树或遍历结束时,p==T */
            while(p->LTag==Link)
                p=p->lchild;
            if(!visit(p->data)) /* 访问其左子树为空的结点 */
                return ERROR;
            while(p->RTag==Thread&&p->rchild!=T)
            {
                p=p->rchild;
                visit(p->data); /* 访问后继结点 */
            }
            p=p->rchild;
        }
        
        return OK;
    }
    
    int main(int argc, const char * argv[]) {
        // insert code here...
        printf("Hello, 线索化二叉树!\n");
        BiThrTree H,T;
        
        //StrAssign(str,"ABDH#K###E##CFI###G#J##");
        StrAssign(str,"ABDH##I##EJ###CF##G##");
        
        CreateBiThrTree(&T); /* 按前序产生二叉树 */
        InOrderThreading(&H,T); /* 中序遍历,并中序线索化二叉树 */
        InOrderTraverse_Thr(H);
        printf("\n\n");
        return 0;
    }
    
    

    相关文章

      网友评论

          本文标题:数据结构与算法 线索二叉树

          本文链接:https://www.haomeiwen.com/subject/ydxlghtx.html