山间桃花纷飞落,撑伞也是雨中人。|

颜欢兮

园龄:2年1个月粉丝:1关注:0

13、线索二叉树

1、线索化二叉树的定义和初始化

复制代码
#include<stdio.h>
#include<malloc.h>
#include<assert.h>

#define ElemType char

typedef struct BinTreeNode{
    ElemType data;
    struct BinTreeNode* leftChild;
    struct BinTreeNode* rightChild;
    int lTage;//左标记[0:左孩子节点 1:前驱节点] 
    int rTage;//右标记[0:右孩子节点 1:后继节点] 
}BinTreeNode;

typedef struct BinTree{
    BinTreeNode* root;
    ElemType refvalue;//停止标志 
}BinTree; 


//初始化
void initBinTree(BinTree* bt,ElemType ref){
    bt->root = NULL;
    bt->refvalue = ref;
} 
复制代码

2、二叉树的创建和线索化

复制代码
//创建节点
BinTreeNode* malloc_node(ElemType data){
    BinTreeNode* t = (BinTreeNode*) malloc(sizeof(BinTreeNode));
    assert(t != NULL);
    t->data = data;
    t->leftChild = NULL;
    t->rightChild = NULL;
    t->lTage = t->rTage = 0;
    return t;
} 

//创建二叉树
void createBinTree(BinTree* bt,BinTreeNode** node,char** str){
    if(**str == bt->refvalue){
        (*node) = NULL;
        ++(*str);
    } else {
        (*node) = malloc_node(**str);
        ++(*str);
        createBinTree(bt,&(*node)->leftChild,str);
        createBinTree(bt,&(*node)->rightChild,str);
    }
} 

//二叉树中序线索化
void BinTreeNodeInThread(BinTreeNode** t,BinTreeNode** pre){
    if(*t == NULL)
        return;
    else {
        //遍历当前节点的所有左子树
        BinTreeNodeInThread(&(*t)->leftChild,pre);
        
        //运行到此处说明该节点 的左子树已全部遍历完
        //处理该节点 将左节点进行线索化
        if((*t)->leftChild == NULL){
            (*t)->lTage = 1;
            (*t)->leftChild = *pre;
        }
        //处理该节点的前驱节点,将该节点的前驱节点线索化[前驱节点的后继指向t] 
        if((*pre) != NULL && (*pre)->rightChild == NULL){
            (*pre)->rTage = 1;
            (*pre)->rightChild = *t;
        }
        //更新前驱节点
        *pre = *t;

        //遍历当前节点的所有右子树
        BinTreeNodeInThread(&(*t)->rightChild,pre);
    }
} 

void BinTreeInThread(BinTree* bt){
    //记录前驱节点 
    BinTreeNode* pre = NULL;
    BinTreeNodeInThread(&bt->root,&pre); 
    //处理最后一个节点
    if(pre != NULL){
        pre->rightChild = NULL;
        pre->rTage = 1; 
    }

} 
复制代码

3、线索化二叉树的其他方法

复制代码
//求中序遍历第一个节点
BinTreeNode* First(BinTreeNode* node){
    
    BinTreeNode* p = node;
    //遍历左孩子,当遍历到左标记为1说明是第一个节点 
    //由于已经线索化了,所有节点的左右孩子都不为NULL 
    while(p != NULL && p->lTage == 0)
        p = p->leftChild;
    return p;
} 

//求中序遍历最后一个节点
BinTreeNode* Last(BinTreeNode* node){
        
    BinTreeNode* p = node;
    while(p != NULL && p->rTage == 0){
        p = p->rightChild;
    }
        
    return p;
} 

//求cur节点的后继
BinTreeNode* Next(BinTreeNode* root,BinTreeNode* cur){
    if(root == NULL || cur == NULL)
        return NULL;
    if(cur->rTage == 1)
        return cur->rightChild;
    //由于是中序遍历,说明cur左子树的节点都遍历完了,
    //所以cur的后继节点为它的右子树遍历的第一个节点
    return First(cur->rightChild); 
} 

//求cur节点的前驱
BinTreeNode* Prio(BinTreeNode* root,BinTreeNode* cur){
    if(root == NULL || cur == NULL)
        return NULL;
    if(cur->lTage == 1)
        return cur->leftChild;
    //由于是中序遍历,cur的前驱为它的左子树遍历的最后一个节点 
    return Last(cur->leftChild); 
} 

//中序遍历[由于二叉树已经线索化,不能再用之前的遍历方法,
//线索化将二叉树 由非线性变为线性关系] 
void InOrder(BinTreeNode* root){
    BinTreeNode* p = root;
    for(p = First(p);p != NULL;p = Next(root,p)){
        printf("%c ",p->data);
    }
    printf("\n");
} 

BinTreeNode* search(BinTreeNode* root,ElemType key){
    if(root == NULL)
        return NULL;
    if(root->data == key)
        return root;
    BinTreeNode* p = root;
    for(p = First(p);p != NULL;p = Next(root,p)){
        if(p->data == key)
            return p;
    }    
    return NULL;
}

BinTreeNode* Parent(BinTreeNode* root, BinTreeNode* cur){
     if (root == NULL || cur == NULL || root == cur) {
        return NULL;
    }
    
    BinTreeNode* p;
    //cur存在线索 注意:if中一定要判断p是否为空 
    if(cur->lTage == 1){
        p = cur->leftChild;
        //由于是中序遍历,cur的左孩子为前驱节点,既然是前驱说明cur一定在指向的右子树这边 
        if(p != NULL && p->rightChild == cur)
            return p;
    }
    if(cur->rTage == 1){
        p = cur->rightChild;
        if(p != NULL  && p->leftChild == cur)
            return p;
    }
     
    //cur不存在线索 ,说明cur存在左子树,那么左子树在cur前面
    //找到cur左子树要显示的第一个节点,该节点一定没有左子树
    //故该节点的左孩子节点会指向它的前驱,这个前驱有可能就是cur的父节点 
    p = First(cur->leftChild);
    p = p->leftChild;
    if(p != NULL && p->rightChild == cur)
        return p;
    
    //如果上诉都没找到,那就找cur节点的右孩子最后中序遍历的最后一个节点
    //这个节点的后继就是cur的父节点,因为这个节点在cur右边,说明cur已经访问了
    //cur的中序遍历最后一个右节点也访问,根据左根右说明下一个就是cur的父节点
    p = Last(cur->leftChild);
    if (p != NULL && p->rightChild == cur) {
        return p;
    }
    return NULL; 
} 
int main(){
    BinTree myTree;
    initBinTree(&myTree,'#');
    char* str = "ABC##DE##F##G#H##";
    createBinTree(&myTree,&myTree.root,&str);
    BinTreeInThread(&myTree);
//    BinTreeNode* node = Last(myTree.root);
//    printf("%c",node->data);
    InOrder(myTree.root);
    BinTreeNode* p = search(myTree.root,'C');
//    BinTreeNode* next = Next(myTree.root,p);
    BinTreeNode* parent = Parent(myTree.root,p);
    printf("%c",parent->data);
    
    return 0;
}
复制代码

 

本文作者:颜欢兮

本文链接:https://www.cnblogs.com/xpp3/p/18438804

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   颜欢兮  阅读(3)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起
  1. 1 《起风了》 林俊杰
  2. 2 晴天 (Live) 林俊杰,周杰伦
  3. 3 兰亭序 (Live) 周杰伦
  4. 4 反方向的钟 (Live) 我也不太了解她
《起风了》 - 林俊杰
00:00 / 00:00
An audio error has occurred, player will skip forward in 2 seconds.

林俊杰-起风了:心之所动就随风去了 - 宝藏挖掘机

词:米果

曲:高桥优

这一路上走走停停

顺着少年漂流的痕迹

迈出车站的前一刻

竟有些犹豫

不禁笑这近乡情怯

不禁笑这近乡情怯

仍无可避免

而长野的天

依旧那么暖

风吹起了从前

从前初识这世间

万般流连

看着天边似在眼前

也甘愿赴汤蹈火去走它一遍

如今走过这世间

如今走过这世间

万般流连

翻过岁月不同侧脸

翻过岁月不同侧脸

措不及防闯入你的笑颜

我曾难自拔于世界之大

我曾难自拔于世界之大

也沉溺于其中梦话

不得真假 不做挣扎 不惧笑话

我曾将青春翻涌成她

也曾指尖弹出盛夏

心之所动 且就随缘去吧

逆着光行走 任风吹雨打

短短的路走走停停

短短的路走走停停

也有了几分的距离

不知抚摸的是故事 还是段心情

也许期待的不过是 与时间为敌

也许期待的不过是 与时间为敌

再次看到你

微凉晨光里

笑的很甜蜜

从前初识这世间

从前初识这世间

万般流连

看着天边似在眼前

也甘愿赴汤蹈火去走它一遍

如今走过这世间

万般流连

翻过岁月不同侧脸

措不及防闯入你的笑颜

我曾难自拔于世界之大

我曾难自拔于世界之大

也沉溺于其中梦话

不得真假 不做挣扎 不惧笑话

我曾将青春翻涌成她

也曾指尖弹出盛夏

心之所动 且就随缘去吧

晚风吹起你鬓间的白发

晚风吹起你鬓间的白发

抚平回忆留下的疤

你眼中 明暗交杂 一笑生花

暮色遮住你蹒跚的步伐

走进床头藏起的画

画中的你 低着头说话

我仍感叹于世界之大

也沉醉于儿时情话

不剩真假 不做挣扎 无谓笑话

我终将青春还给了她

连同指尖弹出的盛夏

心之所动 就随风去了

以爱之名 你还愿意吗