Chinaunix首页 | 论坛 | 博客
  • 博客访问: 4644
  • 博文数量: 6
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 51
  • 用 户 组: 普通用户
  • 注册时间: 2014-08-31 23:39
文章分类
文章存档

2014年(6)

我的朋友
最近访客

分类: C/C++

2014-09-06 23:25:14


点击(此处)折叠或打开

  1. #include <stdio.h>
  2. #include <time.h>
  3. #include <stdlib.h>
  4. #define Thread 0 //线索
  5. #define Link 1 //孩子指针

  6. //--------------------------二叉树存储节点----------------------------------
  7. typedef struct BiNode
  8. {
  9.     char ch;
  10.     int ltag,rtag; //是孩子还是线索的标志位
  11.     struct BiNode *lchild,*rchild;
  12. }BiNode ,*BiTree;

  13. //------------------------打印----------------------------
  14. void print(BiTree T)
  15. {
  16.     printf("%c",T->ch);
  17. }



  18. //-------------------前序创建二叉树---------------------------
  19. /*
  20.   (1)前序创建时最简单的,其他的有点复杂(因为创建头结
  21.      点问题这里不深入讨论,以后都用前序创建)
  22.   (2)用双重指针**T是因为在main中T=NULL直接把空指针T传
  23.      过来会有问题,需要把T的地址传过来
  24. */
  25. void CreatBiTree(BiNode **T)
  26. {
  27.     char c;
  28.     scanf("%c",&c); //不能用fflush,由于是一次过输入多个

  29.     if( ' ' == c )
  30.     {
  31.         *T = NULL;
  32.     }
  33.     else
  34.     {
  35.         *T=(BiNode *)malloc(sizeof(BiNode));
  36.         (*T)->ch = c;
  37.         CreatBiTree(&((*T)->lchild));//别忘了传的是地址,记得加&
  38.         CreatBiTree(&((*T)->rchild));
  39.     }

  40. }




  41. //-------------------------------------前序遍历---------------------------------------
  42. void PreTravelBiTree(BiTree T)
  43. {
  44.     if(T) //别忘了递归反回条件
  45.     {
  46.     print(T);//放在最前面就是前序。。。
  47.     PreTravelBiTree(T->lchild);
  48.     PreTravelBiTree(T->rchild);
  49.     }
  50. }



  51. //-------------------------------------中序遍历---------------------------------------
  52. void MidTravelBiTree(BiTree T)
  53. {
  54.     if(T)
  55.     {
  56.     MidTravelBiTree(T->lchild);
  57.     print(T);
  58.     MidTravelBiTree(T->rchild);
  59.     }
  60. }


  61. //-------------------------------------后序遍历---------------------------------------
  62. void LastTravelBiTree(BiTree T)
  63. {
  64.     if(T)
  65.     {
  66.     LastTravelBiTree(T->lchild);
  67.     LastTravelBiTree(T->rchild);
  68.     print(T);
  69.     }
  70. }






  71. //----------------------前序遍历线索化----------------------------------
  72. /*
  73.  * 如果孩子为空就把标志位变成线索标志位,原来的NULL r/lchild用来储存线索
  74.  *如果孩子不为空,就跳过,并标注为孩子标志位
  75. */

  76. BiTree pre;
  77. PreThreadTree(BiTree T)
  78.     if(T)
  79.     {
  80.         PreThreadTree(T->lchild);
  81.         if( T->lchild == NULL )//由于还不知道下个节点(后继)是哪个,所以这个节点只能算出它的前驱
  82.         {
  83.             T->ltag=Thread;//如果左孩子为空就把标志位变成线索标志位(Thread),存放前一个节点(前驱)pre
  84.             T->lchild=pre;
  85.         }
  86.         else
  87.         {
  88.             T->ltag=Link;
  89.         }
  90.      
  91.         /*
  92.          *这个节点是前一个节点的后继,可以知道前一个节点的
  93.          *后继,前一个节点可以用pre全局变量暂存起来
  94.         */
  95.         if( pre->rchild==NULL )
  96.         {
  97.             pre->rtag=Thread;/*如果右孩子为空就把标志位变成线索标志位(Thread)
  98.                               存放前一个节点pre的后继,就是本次的T*/
  99.             pre->rchild=T;

  100.         }
  101.         else
  102.         {
  103.             pre->rtag=Link;
  104.         }
  105.         pre=T;
  106.         PreThreadTree(T->rchild);
  107.         /*
  108.         if(T->ltag == Link) //前序时记得加上这条判断
  109.         PreThreadTree(T->lchild);
  110.         if(T->rtag == Link)
  111.         PreThreadTree(T->rchild);
  112.         */
  113.     }
  114. }



  115. BiTree ThreadInit(BiTree T)
  116. {
  117.     BiTree p;//头结点
  118.     p = (BiTree)malloc(sizeof(BiNode));
  119.     p->lchild = NULL;
  120.     p->rchild = NULL;
  121.     /*注意,这里之前p->rchild=T;中序遍历头结点指向的不是树根T,如果p->rchild=T,
  122.      *118处会跳过if,以至头结点指向树根,和194行错误,提前退出while循环
  123.      */
  124.     p->ltag = Thread;
  125.     p->rtag = Thread;
  126.     pre = p;//头结点变成前一个节点存放在pre中
  127.     PreThreadTree(T);
  128.     p->lchild=pre;
  129.     /*变成一个循环双向链表,注意由于最后一个节点有可能没有空孩子,存放不了头结点
  130.      *的地址,(也就是说这个双向链表有可能在头结点可以指向尾节点,而尾节点指不向头结点)
  131.     */
  132.     return p;
  133. }


  134. //------------------中序线索二叉树的遍历后继--------------------------------
  135. void PreThreadTravel(BiTree p)
  136. {
  137.     BiTree q;
  138.     printf("\n\n中序线索二叉树的后继遍历:\n");
  139.     while( p != pre )//别忘了循环,到尾节点结束
  140.     {
  141.     if( p->rtag == Thread )
  142.     {
  143.         p=p->rchild;
  144.         print(p);
  145.     }
  146.     else
  147.     {
  148.         q=p->rchild;
  149.         while( q->ltag != Thread )
  150.             q=q->lchild;
  151.         print(q);
  152.         p=q;
  153.     }
  154.     }
  155. }


  156. //---------------------------中序线索二叉树的遍历前继-------------------------------
  157. void LastThreadTravel(BiTree f)

  158. {
  159.     BiTree q,p;
  160.     p=f;
  161.     printf("\n\n中序线索二叉树的前继遍历:\n");
  162.     while( p != f->rchild )//到第一个节点结束(头结点的后继)
  163.     {
  164.     if( p->ltag == Thread )
  165.     {
  166.         p=p->lchild;
  167.         print(p);
  168.     }
  169.     else
  170.     {
  171.         q=p->lchild;
  172.         while( q->rtag != Thread )
  173.             q=q->rchild;
  174.         print(q);
  175.         p=q;
  176.     }
  177.     }
  178. }

  179. //-----------------------------------------------------------------------------------
  180. main()
  181. {

  182.     BiTree T,p;
  183.     T = NULL;

  184.     printf("前序创建输入数据\n");
  185.     CreatBiTree(&T); //由于T=NULL,所以用传指针的地址,即双重指针

  186.     printf("前序遍历打印二叉树:\n");
  187.     PreTravelBiTree(T);
  188.     printf("\n");

  189.     printf("中序遍历打印二叉树:\n");
  190.     MidTravelBiTree(T);
  191.     printf("\n");

  192.     printf("后序遍历打印二叉树:\n");
  193.     LastTravelBiTree(T);
  194.     printf("\n");

  195.     p=ThreadInit(T);//p为建立的线索二叉树的头结点

  196.     PreThreadTravel(p);//中序线索二叉树的遍历前驱
  197.     LastThreadTravel(p);//中序线索二叉树的遍历前继

  198.     return 0;
  199. }

阅读(178) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~