1. #include <iostream> 
  2. #include "tree.h" 
  3.  
  4. using namespace std; 
  5.  
  6. BTNode *pre;  
  7.  
  8. void Thread(BTNode *&p)     //当tag为1 的时候,表示指向的是前驱 或者 后继, 当其值为0的时候,表示指向的是左右子孩子 
  9. { 
  10.     if(p != NULL)            //采用中序遍历 
  11.     { 
  12.         Thread(p->lchild);        // 此处开始遍历左子树 
  13.  
  14.         if(p->lchild == NULL)      //最节点的左子节点进行操作, 如果其值为空的话,就把其指向 前驱节点,并且设置tag值 
  15.         { 
  16.             p->lchild = pre; 
  17.             p->ltag = 1; 
  18.         }else 
  19.             p->ltag = 0; 
  20.         if(pre->rchild == NULL)   //此处对 前驱节点 的右节点进行操作,如果其右节点为空的话,就把它指向其后继节点,也就是p节点 
  21.         { 
  22.             pre->rchild = p; 
  23.             pre->rtag = 1; 
  24.         }else 
  25.             pre->rtag = 0; 
  26.  
  27.         pre = p;              //对pre进行赋值 
  28.  
  29.         Thread(p->rchild); 
  30.     } 
  31. } 
  32. BTNode * CreateThread(BTNode *b)     //此函数是创建线索化二叉树 
  33. { 
  34.     BTNode *root = (BTNode *)malloc(sizeof(BTNode));            //此为头结点 
  35.  
  36.     if(b != NULL)       
  37.     { 
  38.         root->lchild = b;    //把头结点的左子树指向 根节点 
  39.         pre = root;         //pre 的含义为前驱, 初始值为root 
  40.         Thread(b);          //进行线索化 
  41.         pre->rchild = root;      //经过线索化后,pre为最后一个节点, 把最后一个节点的右子树指向root 
  42.         pre->rtag = 1; 
  43.         root->rchild = pre;  //修改root头结点的右指向 
  44.         root->rtag = 1; 
  45.     }else 
  46.     { 
  47.         root->lchild = root;        //如果b为空的话,那么头结点的左子树,直接指向其自身 
  48.     } 
  49.     return root; 
  50. } 
  51.  
  52. BTNode *first(BTNode *root)             //此函数是返回root为根的中序线索树 的第一个节点 
  53. { 
  54.     if(root != NULL) 
  55.     { 
  56.         while(root->ltag == 0)       //规定当tag==0 的时候表明其有左 或者 右子树, 所以此处循环直到其没有左子树的时候,就是求得 
  57.             root = root->lchild;    //其值的时候, 也就是其有前驱的时候 
  58.         return root; 
  59.     } 
  60.     return NULL; 
  61. } 
  62.  
  63. BTNode *next(BTNode *root, BTNode *q)      //此函数是返回q节点的后继节点 
  64. { 
  65.     BTNode *p = q->rchild;         //此处把p指向q的右子节点, 但是q的右子节点不一定是右孩子节点, 还有可能是其后继节点,  当是其后继节点的时候,就达到了访问其祖先节点的目的 
  66.     if(q->rtag == 0)               //当q有右孩子的时候 
  67.         while(p->ltag == 0)           //怎么求后继节点也是遍历左子树??? 
  68.             p = p->lchild;  //p = p->rchild; 
  69.     if(p == root) 
  70.         return NULL; 
  71.     else  return p; 
  72. } 
  73. void forward(BTNode *root)     //正向遍历线索树 
  74. { 
  75.     BTNode *p; 
  76.     for(p = first(root); p != NULL; p = next(root,p)) 
  77.         cout<<p->data<<' '; 
  78.     cout<<endl; 
  79. } 
  80.  
  81. BTNode *last(BTNode *root)     //此函数是返回以root为根的中序线索树中的最后节点 
  82. {                               //最后一个节点就是 头结点的右子树 
  83.     if(root != NULL) 
  84.         return root->rchild; 
  85.     return NULL; 
  86. } 
  87.  
  88. BTNode *last2(BTNode *root)    //此函数同样实现上述功能但是, 是通过向右遍历实现的 
  89. { 
  90.     if(root != NULL) 
  91.     {   root = root->lchild; 
  92.         while(root->rtag == 0) 
  93.             root = root->rchild; 
  94.         return root; 
  95.     } 
  96.     return NULL; 
  97. } 
  98.  
  99. BTNode *prior(BTNode *root, BTNode *q)       //此函数是求的q节点的前驱节点 
  100. { 
  101.     BTNode *p = q->lchild;                 //把p指向q的左节点,且左节点 可能是左孩子节点 也可能是 前驱 
  102.     if(q->ltag == 0)                    //此处判断  q其是否有左孩子节点 
  103.         while(p->rtag == 0) 
  104.             p = p->rchild;        //奇怪这里是对右子树进行判断的, 而求后继的时候是对左子树进行判断的,  想想也是因为他们是连续的 
  105.     if(p == root) 
  106.         return NULL; 
  107.     else return p; 
  108. } 
  109.  
  110. void backward(BTNode *root) 
  111. { 
  112.     BTNode *p; 
  113.     for(p = last(root); p != root; p = prior(root,p)) 
  114.         cout<<p->data<<' '; 
  115.     cout<<endl; 
  116. }