线索化二叉树

722 阅读2分钟
  • 概念

    线索化二叉树说白了就是链式储存结构的二叉树当左右结点为null的时候可以分别指向他的前驱和后继,这样呢解决了无法直接找到该结点在某种遍历序列中的前驱和后继结点的问题,解决了二叉链表找左、右孩子困难的问题,就不需要每次遍历(如果是完全二叉树就没必要线索化了)
  • 线索化二叉树结点

lflag:用来标记左指针指向的是左孩子还是前驱结点
rflag:用来标记右指针指向的是右孩子还是后继结点

  • 线索化二叉树图解

  • 代码实现

#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0

#define Nil ' '

typedef int Status;
typedef char ElemType;  //树结点的字符型,也可以是整型
int indexs = 0;
typedef enum {
    Thread = 0,
    Child
}flag;

typedef struct TreeNode{
    ElemType data;  //数据
    flag lflag,rflag;
    struct TreeNode *lchild; //指向左孩子的指针
    struct TreeNode *rchild; //指向右孩子的指针
}TreeNode, *Tree;

char *TreeStr = "ABDH#K###E##CFI###G#J##";


//初始化
Status initTree(Tree *T){
    *T = NULL;
    return OK;
}

//销毁二叉树
Status DestroyTree(Tree *T){
    if(*T == NULL) return OK;
    if((*T)->lchild){
        DestroyTree(&(*T)->lchild);
    }
    if((*T)->rchild){
        DestroyTree(&(*T)->rchild);
    }
    
    free(*T);
    *T = NULL;
    
    return OK;
}

/* 创建二叉树
按前序输入二叉树中的结点值(字符),#表示空树;
ABDH#K###E##CFI###G#J##
*/
void CreateTree(Tree *T){
    ElemType data;
    
    if(indexs < (int)strlen(TreeStr)){
        
        data = TreeStr[indexs++];
        
        if(data != '#'){
            
            *T = (Tree)malloc(sizeof(TreeNode));
            
            if(*T == NULL) exit(0);
            
            (*T)->data = data;
            
            CreateTree(&((*T)->lchild));
            
            if ((*T)->lchild) (*T)->lflag = Child;
            
            CreateTree(&((*T)->rchild));
            
            if ((*T)->rchild) (*T)->rflag = Child;
            
        }else{
            
            *T = NULL;
            
        }
    }
    
}


//中序遍历将二叉树线索化
Tree preNode = NULL; //上一个指针
void InThreading(Tree T){
    
    if(T == NULL) return;
    
    //遍历左子树
    InThreading(T->lchild);
    
    //判断当前结点的左指针是否是null  是的话则可以指向上一个结点
    //(也就是指向它的前驱结点)
    if(T->lchild == NULL){
        T->lflag = Thread;
        T->lchild = preNode;
    }else{
        T->lflag = Child;
    }
    
    
    //判断上一个结点的右指针是否是null  是的话则可以指向当前结点
    //(也就是指向它的后继结点,当前结点其实就是上一个结点的后继结点)
    if(preNode){
        if(preNode->rchild == NULL){
            preNode->rflag = Thread;
            preNode->rchild = T;
        }else{
            preNode->rflag = Child;
        }
    }
    //将当前结点赋值给上一个结点
    preNode = T;
    
    //然后再继续遍历右子树
    InThreading(T->rchild);
}