zoukankan      html  css  js  c++  java
  • 二叉线索树

    线索化是为了能够像链表一样遍历树。

    线索化概念

    1、前言

    普通二叉树只能找到结点的左右孩子信息,而该结点的直接前驱和直接后继只能在遍历过程中获得。

    若可将遍历后对应的有关前驱和后继预存起来,则从第一个结点开始就能很快“顺藤摸瓜”而遍历整个树了。

    二叉线索树思想是干什么的?

     

    中序遍历这棵树===》转换成链表访问

    2线索化思想

     

    结论:线索化过程就是在遍历过程(假设是中序遍历)中修改空指针的过程:

    将空的lchild改为结点的直接前驱;

    将空的rchild改为结点的直接后继。

     

    3线索化思想训练

     

    请将此树线索化。

     

    1)右空指针线索化:

     

    2)左空指针线索化

     

    3)总结

    线索化的实现

    1)线索化树结点

    typedef  struct BiThrNode /* 二叉线索存储结点结构 */

    {

    char data; /* 结点数据 */

    struct BiThrNode *lchild, *rchild; /* 左右孩子指针 */

    int LTag;

    int RTag; /* 左右标志 */

    } BiThrNode, *BiThrTree;

     

    2)线索化思想分析

     

    线索化的本质:让前后结点,建立关系;

    1)两个辅助指针变量形成差值后:后继结点的左孩子指向前驱结点,前驱结点的右孩子指向后继结点。

    2)赋值指针变量和业务操作的逻辑关系

     

    二叉树线索化树的遍历
    
    /* 中序遍历二叉线索树T(头结点)的非递归算法 */
    int InOrderTraverse_Thr(BiThrNode* T)
    { 
        BiThrNode* p;
        p = T->lchild; /* p指向根结点 */
        while (p != T)
        { 
            /* 空树或遍历结束时,p==T */
            while (p->LTag == Link)
                p = p->lchild;
            printf("%c ", p->data);
            
            while (p->RTag==Thread && p->rchild!=T)
            {
                p = p->rchild;
                printf("%c ", p->data);
            }
            p=p->rchild;
        }
        return 0;
    }

     创建树:

    #define  _CRT_SECURE_NO_WARNINGS 
    #include <stdlib.h>
    #include <string.h>
    #include <stdio.h>
    
    
    typedef struct BiTNode
    {
        int        data;
        struct BiTNode *lchild, *rchild;
    }BiTNode;
    
    typedef struct BiTNode * BiTree;
    
    
    void InOrder(BiTNode *T)
    {
        if (T == NULL)
        {
            return ;
        }
    
        if (T->lchild != NULL)
        {
            InOrder(T->lchild);
        }
    
        printf("%c ", T->data); //
    
        if (T->rchild != NULL)
        {
            InOrder(T->rchild);
        }
    }
    
    // "1##"
    // 124###3##
    
    //创建树 用先序
    BiTNode *BiTree_Creat()
    {
        BiTNode  *tmp = NULL;
        char  ch;
        scanf("%c", &ch);
    
        if (ch == '#')
        {
            return NULL;
        }
        else
        {
            
            tmp = (BiTNode *) malloc(sizeof(BiTNode)); //创建结点
            if (tmp == NULL)
            {
                return NULL;
            }
            tmp->data = ch;
            tmp->lchild = NULL;
            tmp->rchild = NULL; 
            //在创建结点的左子树
            tmp->lchild = BiTree_Creat();
            tmp->rchild = BiTree_Creat();
            return tmp;
        }
    }
    
    //释放树 选释放左子树 在释放右子树 在释放根结点
    void BiTree_Free(BiTNode *T)
    {
        if (T == NULL)
        {
            return ;
        }
    
        if (T->lchild != NULL)
        {
            BiTree_Free(T->lchild); //释放左子树 把左子树的根结点 传给释放函数
            T->lchild = NULL;
        }
    
        if (T->rchild != NULL)
        {
            BiTree_Free(T->rchild);
            T->rchild = NULL;
        }
    
        free(T);
    
        //
    
    }
    void main()
    {
        BiTNode  *T = NULL;
        printf("#号法创建树 请输入字符串 ( 124###3## ): ");
        T  = BiTree_Creat();
        InOrder(T);
    
        BiTree_Free(T);
    
    
        printf("hello...
    ");
        system("pause");
        return ;
    }

    树的线索化:

    #define  _CRT_SECURE_NO_WARNINGS 
    #include "string.h"
    #include "stdio.h"    
    #include "stdlib.h"   
    
    /* Link==0表示指向左右孩子指针, */
    /* Thread==1表示指向前驱或后继的线索 */
    #define Thread 1
    #define Link    0
    
    typedef  struct BiThrNode    /* 二叉线索存储结点结构 */
    {
        char        data;    /* 结点数据 */
        struct BiThrNode *lchild, *rchild;    /* 左右孩子指针 */
        int            LTag;
        int            RTag;        /* 左右标志 */
    } BiThrNode, *BiThrTree;
    
    char Nil='#'; /* 字符型以空格符为空 */
    
    /* 按前序输入二叉线索树中结点的值,构造二叉线索树T */
    BiThrNode* CreateBiThrTree()
    { 
        BiThrNode *tmp = NULL;
        char ch;
        scanf("%c",&ch);
    
        if (ch == '#')
        {
            return NULL;
        }    
        else
        {
            tmp = (BiThrNode *)malloc(sizeof(BiThrNode));
            if (tmp == NULL)
            {
                return NULL;
            }
            memset(tmp, 0, sizeof(BiThrNode));
            tmp->data = ch;
    
            tmp->lchild = CreateBiThrTree(); /* 递归构造左子树 */
            tmp->rchild = CreateBiThrTree();
        }
        return tmp;
    }
    
    BiThrNode  *pre; /* 全局变量,始终指向刚刚访问过的结点 */
    /* 中序遍历进行中序线索化 */
    void InThreading(BiThrNode *p)
    { 
        if(p)
        {
            InThreading(p->lchild); // 递归左子树线索化 
            if(p->lchild == NULL)    // 没有左孩子 
            {
                p->LTag = Thread;      p->lchild = pre;    //前驱线索 左孩子指针指向前驱 
            }
            if(pre->rchild == NULL) // 前驱没有右孩子 
            {
                pre->RTag = Thread;  pre->rchild = p;    // 后继线索 前驱右孩子指针指向后继(当前结点p) 
            }
            pre = p;                // 保持pre指向p的前驱 
            InThreading(p->rchild); // 递归右子树线索化 
        }
    }
    
    /* 中序遍历二叉树T,并将其中序线索化,Thrt指向头结点 */
    BiThrNode* InOrderThreading(BiThrTree T)
    {
        BiThrNode *Thrt = NULL;
    
        Thrt = (BiThrNode *)malloc(sizeof(BiThrNode)); //建头结点 
        if (Thrt == NULL)
        {
            return NULL;
        }
        memset(Thrt, 0, sizeof(BiThrNode));
    
        Thrt->LTag = Link;  //左孩子为孩子指针
        Thrt->RTag = Thread; //右孩子为线索化的指针
        Thrt->rchild = Thrt; // 右指针回指 */  //步骤2和4
        if(T == NULL) // 若二叉树空,则左指针回指 
        {
            Thrt->lchild  = Thrt; //步骤1和3
        }
        else
        {
            Thrt->lchild = T;    //步骤1 
            pre = Thrt ;
            InThreading(T);        // 中序遍历进行中序线索化 
            pre->rchild = Thrt;    //步骤4
            pre->RTag = Thread;    // 最后一个结点线索化 
            Thrt->rchild = pre;    //步骤2
        }
        return Thrt;
    }
    
    /* 中序遍历二叉线索树T(头结点)的非递归算法 */
    int InOrderTraverse_Thr(BiThrNode* T)
    { 
        BiThrNode* p;
        p = T->lchild; /* p指向根结点 */
        while (p != T)
        { 
            /* 空树或遍历结束时,p==T */
            while (p->LTag == Link)
                p = p->lchild;
            printf("%c ", p->data);
    
            //如果中序遍历的最后一个结点的 右孩子 == T 说明到最后一个结点 ,遍历结束..
            while (p->RTag==Thread && p->rchild!=T)
            {
                p = p->rchild;
                printf("%c ", p->data);
            }
            p = p->rchild;
        }
        return 0;
    }
    
    /* 中序遍历二叉线索树T(头结点)的非递归算法 */
    int InOrderTraverse_Thr2(BiThrNode* T)
    { 
        BiThrNode* p;
        p = T->rchild; /* p指向根结点 */
        while (p != T)
        { 
            /* 空树或遍历结束时,p==T */
            while (p->RTag == Link)
                p = p->rchild;
            printf("%c ", p->data);
    
            //如果中序遍历的最后一个结点的 右孩子 == T 说明到最后一个结点 ,遍历结束..
            while (p->LTag==Thread && p->lchild!=T)
            {
                p = p->lchild;
                printf("%c ", p->data);
            }
            p = p->lchild;
        }
        return 0;
    }
    
    
    int main()
    {
        BiThrTree T, H;
        printf("请按前序输入二叉树(如:'ABDH##I##EJ###CF##G##')
    ");
        T = CreateBiThrTree(); // 按前序产生二叉树 
        H = InOrderThreading(T); // 中序遍历,并中序线索化二叉树 
        printf("中序遍历(输出)二叉线索树:
    ");
        InOrderTraverse_Thr(H); // 中序遍历(输出)二叉线索树 
    
        printf("
    逆序访问:");
        InOrderTraverse_Thr2(H);
    
        printf("
    ");
    
        system("pause");
        return 0;
    }

     04 09完

  • 相关阅读:
    C语言I博客作业09
    C语言I博客作业08
    第十四周助教总结
    C语言I博客作业07
    第十三周助教总结
    C语言I博客作业06
    第十二周助教总结
    学期总结
    C语言I博客作业09
    C语言I博客作业08
  • 原文地址:https://www.cnblogs.com/yaowen/p/4813298.html
Copyright © 2011-2022 走看看