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

                            线索二叉树

    基本概念:

      n个结点的二叉链表中共有2n个链域,但只有n-1个有用的非空链域,其余n+1个是空的,利用这n+1个空链域来存放遍历过程中结点的前驱和后继;规定:若结点有左子树,则其LChild指向左孩子,否则LCHild指向前驱;若结点有右子树,则其RChild域指向右孩子,否则指向后继。

      Ltag=0,CHild指向左孩子;Ltag=1,CHild指向遍历的前驱

      Rtag=0,RHild指向左孩子;Rtag=1,RHild指向遍历的前驱

      指向前驱和后继的指针称为线索。以这种结构组成的二叉链表作为二叉树的存储结构,称为线索链表。对二叉树以某种次序进行遍历并且加上线索的过程称为线索化。线索化的二叉树称为线索二叉树

    算法思想:

    1. 中序线索化采用中序递归遍历算法框架
    2. 加线索的操作就是访问结点的操作
    3. 加线索操作需要利用刚访问的结点与当前节点的关系,因此设置一个指针pre,始终记录刚访问过的结点,操作如下

        a.如果当前遍历结点root的左子域为空,左子域指向pre;

        b.如果前驱pre的右子域为空,则让右子域指向当前遍历结点root;

        c.为下次做准备,访问当前结点root作为下一个访问结点的前驱pre

    废话不多说了,直接上代码:

    #include <stdio.h>
    #include <stdlib.h>
    
    typedef struct Tree
    {
        int data,Ltag,Rtag;//数据,左右标志 
        struct Tree *LChild,*RChild;//左右孩子指针域 
    }Tree,*Trees;
    Trees pre=NULL;
    
    void InitTree(Trees *boot)//初始化二叉树,只有一个根节点,无左右孩子 
    {
        *boot=(Trees)malloc(sizeof(Tree));
        (*boot)->LChild=(*boot)->RChild=NULL;
        (*boot)->Ltag=(*boot)->Rtag=0; 
    }
    
    void CreateTree(Trees &boot)//创建二叉树,具体操作参考上一篇《树与二叉树》 
    {
        int ch;
        scanf("%d",&ch);
        if(ch==0)
            boot=NULL;
        else
        {
            boot=(Trees)malloc(sizeof(Tree));
            boot->data=ch;
            boot->LChild=boot->RChild=NULL;
            boot->Ltag=boot->Rtag=0;
            CreateTree(boot->LChild);
            CreateTree(boot->RChild);
        }
    }
    //添加线索 
    void InThread(Trees &boot)
    {
        if(boot!=NULL)
        {
            InThread(boot->LChild);//线索化左子树 
            if(boot->LChild==NULL)
            {
                boot->Ltag=1;
                boot->LChild=pre;//置前驱线索 
            }
            if(pre!=NULL&&pre->RChild==NULL)
            {
                pre->RChild=boot;
                pre->Rtag=1;
            }
            pre=boot;//当前访问节点为下一个访问节点的前驱 
            InThread(boot->RChild);//线索化右子树 
        }
    } 
    
    Trees InOrderThread(Trees &rt)//建头结点 
    {
        Trees thrt;
        if(!(thrt=(Trees)malloc(sizeof(Tree))))
        {
            printf("头结点创建失败.
    ");
            exit(1);
        }
        
        thrt->Ltag=0;//等于零指向左孩子  1
        thrt->Rtag=1;//等于一指向遍历的前驱 2
        thrt->RChild=thrt;//右回指针,指向自己(头结点) 3
        if(!rt)
            thrt->LChild=thrt;//若二叉树为空,建立左回指针(也指向头结点)
        else
        {
            thrt->LChild=rt;//rt==boot,也就是二叉树的根 
            pre=thrt;//pre指向头结点 
            InThread(rt);//为二叉树加线索 
            pre->RChild=thrt;//同上1
            pre->Rtag=1;//同上2
            thrt->RChild=pre;//同上3
        }
        return thrt;
    }
    
    //中序找前驱 
    void InPre(Trees boot)
    {
        Trees q=NULL;
        if(boot->Ltag==1)
            pre=boot->LChild;
        else
        {
            for(q=boot->LChild;q->Rtag==0;q=q->RChild)
                pre=q;    
        }    
        if(pre)
            printf("中序找到的前驱为:%d
    ",pre->data);    
        else
            printf("无前驱.
    ");
    }
    
    //中序找后继 
    void InNext(Trees boot)
    {
        Trees q=NULL;
        if(boot->Rtag==1)
            pre=boot->RChild;
        else
        {
            for(q=boot->RChild;q->Ltag==0;q=q->LChild)
                pre=q;
        }
        if(pre)
            printf("中序找到的后继为:%d
    ",pre->data);
        else
            printf("中序遍历无后继.
    ");
    }
    
    //中序遍历序线索树上的第一个结点 
    Trees InFirst(Trees boot)
    {
        Trees p=boot;
        if(!p)
            return NULL;
        while(p->Ltag==0)
            p=p->LChild;
        return p;
    }
    
    //中序遍历线索二叉树 
    void TInOrder(Trees &thrt)
    {
        Trees p;
        p=thrt->LChild;
        while(p!=thrt)
        {
            while(p->Ltag==0)
                p=p->LChild;
            printf("%d ",p->data);
            while(p->Rtag==1&&p->RChild!=thrt)
            {
                p=p->RChild;
                printf("%d ",p->data);        
            }
            p=p->RChild;
        }
        printf("
    ");
    }
    
    int main()
    {
        Trees boot=NULL;
        printf("创建二叉树,输入零结束:
    ");
        CreateTree(boot);
        
        Trees thrt;//头结点 
        thrt=InOrderThread(boot);
        TInOrder(thrt);//中序遍历线索二叉树 
        
        InPre(boot);//中序找前驱 
        
        InNext(boot);//中序找后继 
        
        Trees bt=InFirst(boot);//中序遍历序线索树上的第一个结点
        printf("中序遍历序线索树上的第一个结点为:%d
    ",bt->data);
        
        return 0;
    }

     结果:

      

  • 相关阅读:
    Introduction to debugging neural networks
    Faster R-CNN教程
    最长递增子序列
    321. Create Maximum Number 解题方法详解
    Ubuntu安装opencv with cuda
    转载:LeetCode:5Longest Palindromic Substring 最长回文子串
    64. Minimum Path Sum
    322. Coin Change
    148. Sort List
    微信浏览器禁止页面下拉查看网址(不影响页面内部scroll)
  • 原文地址:https://www.cnblogs.com/tianzeng/p/9688616.html
Copyright © 2011-2022 走看看