• 线索树的建立与遍历


    在建立二叉树的时候发现,那些叶节点的左孩子和右孩子的指针域都是空的,浪费空间,这时候就可以将这些空间利用起来,让遍历更加方便,这就是线索树存在的原因,线索树实现完了之后其实会发现就是一个双向链表,那种遍历就容易的多了。

      1 #include <stdio.h>
      2 #include <stdlib.h>
      3 
      4 typedef char ElemType; //数据类型
      5 typedef enum {Link,Thread} childTag; //Link表示结点,Thread表示线索
      6 typedef struct bitNode
      7 {
      8     ElemType data;
      9     struct bitNode *lchild,*rchild;
     10     int ltag,rtag;
     11 } bitNode ,*bitTree;
     12 
     13 void create_tree(bitTree *T,char **arr); //创建二叉树
     14 void pre_order_traverse(bitTree T,int level); //前序遍历二叉树
     15 void in_order_threading(bitTree T); //中序遍历线索化
     16 void in_thread(bitTree *P,bitTree T); //新加入一个头结点,让二叉树成一个封闭环
     17 void in_order_traverse(bitTree T); //中序遍历二叉树(带有头结点)
     18 void visit(bitTree T); //访问结点信息
     19 
     20 bitTree pre; //表示上次刚刚访问的结点
     21 
     22 int main()
     23 {
     24   bitTree P,T;
     25   int level =1; //表示该结点的深度
     26   char *arr="ab d  ce   "; //构造二叉树所需结点(按前序遍历方式输入), 只是实验数据, 也可以从键盘输入
     27   create_tree(&T,&arr); //构造二叉树
     28   printf("pre-order-traverse
    ");
     29   pre_order_traverse(T,level); //前序遍历输出二叉树
     30   printf("
    in-order-traverse
    ");
     31   in_thread(&P,T); //二叉树线索化
     32   in_order_traverse(P); //输出线索化后的二叉树
     33   return 0;
     34 }
     35 
     36 /*
     37 创建二叉树,其输入必须按照前序遍历的次序。
     38 T:二叉树根节点
     39 arr:按照前序遍历次序排列的各节点的值。无孩子结点时用空格代替
     40 */
     41 void create_tree(bitTree *T,char **arr)
     42 {
     43     char c;
     44     sscanf(*arr,"%c",&c); //读入一个结点值
     45     (*arr)++;
     46     if(' '==c) //如果是空格,表示空结点
     47     {
     48         *T=NULL;
     49     }
     50     else
     51     {
     52         *T=(bitTree)malloc(sizeof(bitNode)); //构造新结点
     53         (*T)->data=c;
     54         (*T)->ltag=Link;
     55         (*T)->rtag=Link;
     56         create_tree(&(*T)->lchild,arr);//构造新结点的左孩子
     57         create_tree(&(*T)->rchild,arr);//构造新结点的右孩子
     58     }
     59 }
     60 
     61 /*
     62 前序遍历访问二叉树
     63 */
     64 void pre_order_traverse(bitTree T,int level)
     65 {
     66     if(T)
     67     {
     68         visit(T);
     69         pre_order_traverse(T->lchild,level+1);
     70         pre_order_traverse(T->rchild,level+1);
     71     }
     72 }
     73 
     74 /*
     75 中序遍历二叉树,对其进行线索化
     76 */
     77 void in_order_threading(bitTree T)
     78 {
     79     if(T)
     80     {
     81         in_order_threading(T->lchild); //左孩子线索化
     82         if(!T->lchild) //如果左孩子为空,则将其指向直接前驱
     83         {
     84             T->lchild=pre;
     85             T->ltag=Thread;
     86         }
     87         if(!pre->rchild) //如果上一个结点的右孩子为空,则将其指向直接后继。(注意:只有访问到下一个结点时,才会知道本结点的后继是谁)
     88         {
     89             pre->rchild=T;
     90             pre->rtag=Thread;
     91         }
     92         pre=T;
     93         in_order_threading(T->rchild); //右孩子线索化
     94     }
     95 }
     96 
     97 /*
     98 加入一个头结点,使二叉线索树成一个封闭环
     99 P:带有头结点的二叉树。头结点的左孩子指向二叉树T;右孩子指向T树中的最后一个叶子结点
    100 T:不带有头结点的二叉树。
    101 */
    102 void in_thread(bitTree *P,bitTree T)
    103 {
    104     (*P)=(bitTree)malloc(sizeof(bitNode)); //构造新加入的头结点
    105     (*P)->ltag=Link;
    106     (*P)->rtag=Thread;
    107     (*P)->rchild=*P;
    108     if(!T) //如果二叉树为空,则P的孩子指向自己。
    109     {
    110         (*P)->lchild=*P;
    111     }
    112     else
    113     {
    114         (*P)->lchild=T;
    115         pre=*P;
    116         in_order_threading(T); //对二叉树进行线索化
    117         (*P)->rchild=pre; //将头结点右孩子指向最后一个叶子结点
    118         pre->rtag=Thread; //将最后一个叶子结点的右孩子指向头结点。这样,环就形成了。
    119         pre->rchild=*P;
    120     }
    121 }
    122 
    123 /*
    124 非递归方式:中序遍历二叉树(树必须带有头结点,且已经线索化)
    125 P:带有头结点的二叉树
    126 */
    127 void in_order_traverse(bitTree P)
    128 {
    129     bitTree T;
    130     T=P->lchild;
    131     while(T!=P) //判断是否空树
    132     {
    133         while(T->ltag==Link) //从左孩子开始,直到叶子结点
    134         {
    135             T=T->lchild;
    136         }
    137         visit(T);
    138         while(T->rtag==Thread && T->rchild!=P) //根据线索,访问后继结点。并且后继结点不是指向头结点的
    139         {
    140             T=T->rchild;
    141             visit(T);
    142         }
    143         T=T->rchild;
    144     }
    145 }
    146 
    147 /*
    148 访问结点信息
    149 */
    150 void visit(bitTree T)
    151 {
    152     printf("%c ",T->data);
    153 }
  • 相关阅读:
    338. 比特位计数
    300.最长上升子序列
    git 钩子服务代码
    thinkphp5.1 封装文件上传模块
    Theano 基础
    使用anaconda和pycharm搭建多python本版的开发环境
    GIT常用命令
    Thinkphp 获取数据表随机值
    在Windows中利用.bat提交git代码到不同分支
    Windows .bat 常量
  • 原文地址:https://www.cnblogs.com/Howe-Young/p/4008425.html
Copyright © 2020-2023  润新知