将节点作为模板参数的二叉树的设计,以及常用二叉树算法(求公共祖先等)的实现...

     一般都是将节点数据类型作为二叉树模板的参数,这里尝试使用将节点类型直接作为二叉树的模板参数,例如一棵二叉树可以装配普通的二叉树节点,也可以装配带有父指针的三叉链表节点,或者装配线索二叉树节点。只是作为尝试,其实也许直接定义三叉链表二叉树,线索二叉树的设计更好。另外尝试了使用triats手法,以及提出基类进行模板特化private BinaryTreeHelper<U,T>,因为函数不能偏特化。采用triats以及提出基类模版特化的方法是为了对于不同的节点我们可能会对相同的接口采用不同的实现,例如求最近的公共祖先,对于三叉链表节点和二叉节点链表,我们给出不同的实现,但是接口任然是统一的,同名Ancestor,这里求最近公共祖先采用的提出基类偏特化的方法实现,对于PrintTree实验triats方法,这里针对比如我的node是线索二叉树的节点,它的left,right的含义有所不同所以对于普通二叉树节点写的打印tree的方法是不适合线索二叉树的利用triats可以判断是线索二叉树节点,并根据它采用不同的实现方案。个人感觉triats方法效果更好些,提出基类偏特化增加了类的层次,代码复杂度提高。
     实现了常用二叉树算法,如用户交互输入构造二叉树,二叉树的各种遍历,非递归的遍历,二叉树打印,树的高度,表达式二叉树的一些算法,还有求两个节点的最近祖先( 这个自己想出来并实现验证过的竟然面试的时候一片空白,晕死),好吧再总结下,
1.如果有parent域,其实相当于链表求交点,可以用栈辅助,如果节点记录有height域的话,可以让height大的节点先往上走直到两个节点等高,这样然后两个节点(如果此时没有相交)一起向上走,直到遇到交点即为最近的公共祖先。避免走不必要的后序节点。暂时没想出更好的方法。看了下标准答案,是先求的顶点高度,这样实现起来比较方便但是复杂度上看不出比用栈辅助有啥多余的好处。
2.如果没有parent域,按照非递归的后序遍历框架找即可,当找到第一个节点的时候,以后再入栈的节点做标记标明是找到一个节点之后又入栈的,当找到第二个节点的时候,后序遍历结束退出。查看栈中节点,不断pop直到找到第一个在栈里的并且是在找到第一节点之前就入栈的节点(在它的左子树中找到了第一个节点,在它的右子树中找到了第二个节点,如果p,q互为父子也是这个节点)。它就是最近的公共祖先。
另外还有一种递归的方法,即如果在左子树中找到p,q返回左子树根,如果在右子树中找到p,q返回右子树根,如果在左子树找到一个,右子树找到另一个,或者在两个子树中找到一个,而自身就等于p或者q,返回自己,其余情况返回Null.此外在找到第二个后立即返回剪枝,不进行后续遍历。
递归的思路似乎更直接,不过我开始没有意识到。利用递归的返回值,将结果从底层,层层向上传递是一种常用的递归技巧,例如求树高,查找某个等于key的节点并返回所在的层次等等。下面贴下标准答案的代码,还是很清晰的.
          a .   find == 1
      b.
  c.   find ==2
 假如在a 处找到第一个节点p,在c处找到第二个节点q,那么c的左右子树无需访问了,注意对于b而言它仅仅在它的左子树中找到一个,但是b的左子树遍历完之后由于当前find==2了已经,所以b的右子树无需访问。
//采用递归计算两个节点最近公共祖先,当然如果需要连续计算ancestor不能用static 
 1 template<class T>
 2 BinaryTreeNode<T> *Ancestor(BinaryTreeNode<T> *root,
 3 BinaryTreeNode<T> *p, BinaryTreeNode<T> *q) // 先序遍历
 4 {
 5     static int found = 0;
 6     int isroot = 0, isinleft = 0, isinright = 0// 根及左右子树是否有目标节点,取值{0, 1}
 7     BinaryTreeNode<T> *ptr; // 临时变量
 8     if (root == p || root == q) { found++; isroot = 1; }
 9     if (found == 2return NULL; // 忽略后面的遍历
10     if (root->leftchild()) {
11         isinleft = found;
12         if (ptr = Ancestor(root->leftchild(), p, q)) return ptr; // 左子树中找到p、q
13         isinleft = found - isinleft; // 是否左子树有一个目标节点
14         if (isroot && isinleft) return root; // 左子树中找到一个,根也是其中一个
15     }
16     if (found == 2return NULL; // 忽略后面的遍历,chg add这个剪枝很强...
17     if (root->rightchild()) {
18         isinright = found;
19         if (ptr = Ancestor(root->rightchild(), p, q)) return ptr; // 右子树中找到p、q
20         isinright = found - isinright; // 是否右子树有一个目标节点
21         if ((isroot || isinleft) && isinright) return root; // 左右子树各一个,或右子树一个根也是一个
22     }
23     return NULL; // 不能在该子树中同时找到p和q
24 }
//下面的binary_tree.h中有利用后序遍历非递归框架,找两个节点最近公共祖先的代码

                           a
          b                                     e
 
c(find ==1)                        f
    d                                           g (find==2)           
例如对于上面的例子,假如在c找到第一节点p,以后所有的入栈操作都被标记是在找到第一个节点之后入栈的,
那么按后序遍历顺序a,b,c是在找到第一个节点之前入栈的,之后d入栈退栈,
c,b退栈来到a,e,f,g入栈但是注意我们会加相应的标记,标明它们是在找到第一个节点之后入栈的,所以在g找到
第二个节点之后,不断退栈将g,e,f pop出去,到了a因为它的标记标明它是在找到第一个节点之前就入栈的,所以
a就是最近公共祖先.
下面给出对应这种方法的递归算法,其实本质上和上面的算法是一致的,所谓找在第一个节点被找到之前入栈,其实
就是为了保证是在它的子树中(或者它本身)找到的第一个节点。
  1 template<typename U, typename T>
  2 class BinaryTreeHelper
  3 {
  4     protected:
  5         void CreateTreeHelper(T *&root, U end_mark); 
  6         T* AncestorHelper(T *root, T *p, T *q);
  7         T* AncestorHelperRec1(T *root, T *p, T *q) {
  8             int found = 0;
  9             return AncestorHelperRec1Helper(root, p, q, found);
 10         }
 11         T* AncestorHelperRec1Helper(T *root, T *p, T *q, int &found);
 12         T* AncestorHelperRec2(T *root, T *p, T *q) {
 13             int found = 0;
 14             bool flag = 0;
 15             return AncestorHelperRec2Helper(root, p, q,found, flag);
 16         }
 17         T* AncestorHelperRec2Helper(T *root, T *p, T *q, int &found, bool flag);
 18 };
 19 template<typename U, typename T>
 20 * BinaryTree<U,T>::Ancestor(T *p, T * q)
 21 {
 22     ///using post order visit 
 23     //return this->AncestorHelper(m_root, p, q);
 24     
 25     ///simple rec
 26     //return this->AncestorHelperRec1(m_root, p, q);
 27     
 28     ///post order visit rec
 29     return this->AncestorHelperRec2(m_root, p, q);
 30 }
 31 //非递归后续遍历,求最近公共祖先节点
 32 template <typename U, typename T>
 33 * BinaryTreeHelper<U,T>::AncestorHelper(T *root, T *p, T *q)
 34 {
 35     if (p == q)
 36         return p;
 37     if (p == root || q == root)
 38         return root;
 39     T *pcur = root;
 40     stack< T * > s;
 41     stack<bool> ss;        //标示有没有进入右子树(是否是从右子树返回该节点)
 42     int find = 0;
 43     int flag = 0;
 44     stack<bool> fs;     //flag stack 标示是否是已经找到了第一个之后再入栈
 45     while (!s.empty() || pcur ) {
 46         if (pcur) {
 47             s.push(pcur);
 48             ss.push(0);
 49             fs.push(flag);          //well 这里代码顺序重要的,如果在后面,则当前这个的flag为1就出问题了,因为p,q可能本身就是所求最近祖先
 50             if (pcur == p || pcur == q) { //如果定义不允许自身为自身的祖先,那么就应该把fs.push(flag)放在后面,这样会p->parent返回
 51                 find++;                     //如果p是q的祖先的话
 52                 if (find == 1)  //我们找到了一个
 53                     flag = 1;
 54                 else            //找到两个
 55                     break;
 56             }
 57             pcur = pcur->left();
 58         } else {
 59             pcur = s.top();
 60             if (ss.top()) {    
 61                 s.pop();
 62                 ss.pop();
 63                 fs.pop();
 64                 pcur = NULL;   
 65             } else {
 66                 ss.top() = 1;
 67                 pcur = pcur->right();
 68             }
 69         }
 70     }
 71     assert(find == 2);      //如果没能够在二叉树中全部找到p,q,输入有误
 72     assert(!fs.empty());
 73     while (fs.top()) {
 74         fs.pop();
 75         s.pop();
 76     }
 77     assert(!s.empty());
 78     return s.top();
 79 }
 80 
 81 
 82 //这个会假定p与q不相同,利用递归返回值计算最近祖先
 83 template <typename U, typename T>
 84 * BinaryTreeHelper<U,T>::AncestorHelperRec1Helper(T *root, T *p, T *q, int &found)
 85 {
 86     //static int found = 0;
 87     int isinroot = 0, isinleft = 0, isinright = 0;
 88     T *ptr;
 89     if (p == root || q == root) {
 90         found++;
 91         isinroot = 1;
 92     }
 93     if (found == 2)
 94         return NULL;
 95     if (root->left()) {
 96         isinleft = found;  //save found before going left
 97         if (ptr = AncestorHelperRec1Helper(root->left(), p, q, found))  //find p,q in left sub tree
 98             return ptr;
 99         isinleft = found - isinleft;   //mark if we find one in left
100         if (isinroot && isinleft)  //find one in root one left
101             return root;
102     }
103     if (found == 2)
104         return NULL;
105     if (root->right()) {
106         isinright = found;
107         if (ptr = AncestorHelperRec1Helper(root->right(), p, q, found)) //find p,q in right sub tree
108             return ptr;
109         isinright = found - isinright;  //mark if we find one in right
110         if ((isinroot || isinleft) && isinright) //find one left and one right or find one in root and one right
111             return root;
112     }
113     return NULL;
114 }
115 
116 //按后序遍历的思路,但是采用递归
117 template <typename U, typename T>
118 * BinaryTreeHelper<U,T>::AncestorHelperRec2Helper(T *root, T *p, T *q, int &found, bool flag)
119 {
120     if (root == p || root == q) 
121         found++;
122    
123     if (found == 2return NULL;
124     
125     int next_flag = 0;
126     if (found == 1)
127         next_flag = 1;  //此后的状态,已经找到一个之后再入栈了
128 
129     T *ptr;
130     if (root->left()) {
131         if (ptr = AncestorHelperRec2Helper(root->left(), p, q, found, next_flag))
132             return ptr;
133     }
134 
135     if (found == 2) {
136         if (!flag)
137             return root;
138         else  
139             return NULL;
140     }
141 
142     if (found == 1)
143         next_flag = 1;
144 
145     if (root->right()) {
146         if (ptr = AncestorHelperRec2Helper(root->right(), p, q, found, next_flag))
147             return ptr;
148     }
149 
150     if (!flag && found == 2)
151         return root;
152     else
153         return NULL;
154 }
155 


//simple_binary_tree.h
  1  #ifndef _SIMPLE_BINARY_TREE_H
  2  #define  _SIMPLE_BINARY_TREE_H
  3 
  4  using   namespace  std;
  5  namespace  binary_tree{
  6 
  7  struct  normal_node_tag {};       // 标记普通的二叉树节点,带左右孩子指针
  8  struct  with_parent_node_tag:  public  normal_node_tag{};  // 标记带parent域的二叉树节点
  9  struct  with_thread_node_tag:  public  normal_node_tag {};  // 标记利用空指针记录线索的二叉树节点
 10  template  < typename NodeT >
 11  struct  node_traits {
 12      typedef typename NodeT::node_category node_category;
 13  };
 14 
 15  template  < typename U, typename T >
 16  class  BinarySearchTree;      // forward declaration of BinarySearchTree
 17 
 18  // 定义一个独立的二叉树节点类,因为swig似乎不支持嵌套模板
 19  template < typename U >
 20  class  SimpleBinaryTreeNode {
 21      public :
 22          typedef SimpleBinaryTreeNode T;
 23          typedef normal_node_tag node_category;
 24          
 25          template  < typename type1, typename type2 >   friend  class  BinaryTree;
 26          template  < typename type1, typename type2 >   friend  class  BinaryTreeHelper;
 27          template  < typename type1, typename type2 >   friend  class  BinarySearchTree;
 28          SimpleBinaryTreeNode() : m_left (NULL), m_right (NULL) {}
 29          SimpleBinaryTreeNode( const  U &  elem, T  *  left  =  NULL, T  *  right  =  NULL)
 30                  : m_elem (elem), m_left (left), m_right (right) {}
 31 
 32           // accessors
 33           // return the current node data 如果不加const修饰也要注意是只读的因为返回的是临时变量
 34           // ok 为了方便,暂时先不加了
 35          U elem()  const  {   //  TODO  如果 const U elem() const 那么后面用到elem()的函数参数也要const
 36               return  m_elem;       // BinaryTree的也要用const 比如 travel(T* root) { travel root->left()}
 37          }                        // 是错误的,因为root->left()返回const 然后 travel(root->left()),试图转为non const
 38           // return left child
 39          T  *  left()  const  {    //  T const * left()   //  const pointer non const data it points
 40               return  m_left;
 41          }
 42           // return right child
 43          T  *  right()  const  {
 44               return  m_right;
 45          }
 46           //  return 1 if the node is a leaf
 47           bool  IsLeaf()  const  {
 48               return   ! m_left  &&   ! m_right;
 49          }
 50           // mutators
 51           // set current node data
 52           void  set_elem( const  U  &  elem) {
 53              m_elem  =  elem;
 54          }
 55           // set left child tree
 56           void  set_left(T  * left) {
 57             m_left  =  left;
 58          }
 59           // set right child tree
 60           void  set_right(T  * right) {
 61              m_right  =  right;
 62          }
 63 
 64       private :
 65          U m_elem;
 66          T  * m_left;
 67          T  * m_right;
 68  };
 69 
 70  template < typename U, typename T >
 71  class  SimpleBinaryTree {
 72       public :
 73          template  < typename type1, typename type2 >  friend  class   BinaryTreeHelper;  // 要用到m_root
 74           // 如果改变一下三叉树建立函数,不用引用的化,left = Create.() 这样就可以不用私有变量
 75          SimpleBinaryTree ( T  * root  =  NULL ) : m_root ( root ) {}
 76           // ~BinaryTree(){cout << "destruct" << endl;}
 77           virtual   ~ SimpleBinaryTree() {
 78              DeleteBinaryTree(m_root);
 79          }
 80 
 81           // accessors
 82           // return root of the tree
 83          T *  root()  const
 84          {
 85               return  m_root;
 86          }
 87           // rturn left child of the current node
 88          T *  left_child_of ( T  * current )  const
 89          {
 90               return  current -> left();
 91          }
 92           // return right child of the current node
 93          T *  right_child_of ( T  * current )  const
 94          {
 95               return  current -> right();
 96          }
 97           // 判空
 98           bool  IsEmpty()  const
 99          {
100               return  ( m_root == NULL );
101          }
102 
103          //  TODO temp change 如果你希望在别的地方直接建树,就需要public它,否则要不断加friend但这样比较危险
104           void  set_root(T  * root) {
105              m_root  =  root;
106          }
107 
108           void  DeleteBinaryTree(T  * root) 
109          {
110               if  ( root )
111              {
112                  DeleteBinaryTree ( root -> left() );
113                  DeleteBinaryTree ( root -> right() );
114                  delete root;
115              }
116          }
117 
118           virtual   int  Depth(T  * root) {
119               if  (root) {
120                   int  left_depth  =  Depth(root -> left());
121                   int  right_depth  =  Depth(root -> right());
122                   if  (left_depth  >=  right_depth) 
123                       return  left_depth  +   1 ;
124                   else
125                       return  right_depth  +   1 ;
126                   // int depth = left_depth >= right_depth ? left_depth +1 , right_depth + 1;
127              }  else  {
128                   return   0 ;
129              }
130          }
131       protected :
132          T *  m_root;
133  };
134 
135  //  end of namespace binary_tree
136 
137  #endif   //  end of _SIMPLE_BINARY_TREE_H
138 

//binary_tree.h
  1  // 按照PKU课本实现的二叉树
  2  // BinaryTreeNode类统一处理内部节点和叶节点
  3  // 完成了作业3的全部习题
  4  // 用模板取代了多态(指叶节点)
  5  // 同时实现了带parent域的叶节点,它适合二叉树的所有函数
  6  // 除了CreateTree和Ancestor需要不同实现,利用了私有继承
  7  // 和特化,也可以利用复合,但嵌套模板类出了点问题
  8  //  可以说三叉链表二叉树和普通二叉树是有着相同对外接口的
  9  //  树。而穿线二叉树要对外有不同的接口
 10  #ifndef _BINARY_TREE_NODE_H
 11  #define  _BINARY_TREE_NODE_H
 12 
 13  // #define NULL (void *)0
 14  #define  DISALLOW_COPY_AND_ASSIGN(TypeName) \
 15      TypeName( const  TypeName & ); \
 16       void   operator = ( const  TypeName & )
 17  #include  < iostream >
 18  #include  < vector >
 19  #include  < queue >
 20  #include  < string >
 21  #include  < assert.h >
 22  #include  < stack >
 23  #include  < iomanip >
 24 
 25  #include  " simple_binary_tree.h "
 26  using   namespace  std;
 27  namespace  binary_tree{
 28 
 29  // template <typename U, typename T>
 30  // class BinarySearchTree;      // forward declaration of BinarySearchTree
 31  template  < typename U, typename T >
 32  class  BinaryTreeNodeBase
 33  {
 34       public :
 35          template  < typename type1, typename type2 >   friend  class  BinaryTree;
 36          template  < typename type1, typename type2 >   friend  class  BinaryTreeHelper;
 37          template  < typename type1, typename type2 >   friend  class  BinarySearchTree;
 38          BinaryTreeNodeBase() : m_left (NULL), m_right (NULL) {}
 39          BinaryTreeNodeBase( const  U &  elem, T  *  left  =  NULL, T  *  right  =  NULL)
 40                  : m_elem (elem), m_left (left), m_right (right) {}
 41 
 42           // accessors
 43           // return the current node data 如果不加const修饰也要注意是只读的因为返回的是临时变量
 44           // ok 为了方便,暂时先不加了
 45          U elem()  const  {   //  TODO  如果 const U elem() const 那么后面用到elem()的函数参数也要const
 46               return  m_elem;       // BinaryTree的也要用const 比如 travel(T* root) { travel root->left()}
 47          }                        // 是错误的,因为root->left()返回const 然后 travel(root->left()),试图转为non const
 48           // return left child
 49          T  *  left()  const  {    //  T const * left()   //  const pointer non const data it points
 50               return  m_left;
 51          }
 52           // return right child
 53          T  *  right()  const  {
 54               return  m_right;
 55          }
 56           //  return 1 if the node is a leaf
 57           bool  IsLeaf()  const  {
 58               return   ! m_left  &&   ! m_right;
 59          }
 60           // mutators
 61           // set current node data
 62           void  set_elem( const  U  &  elem) {
 63              m_elem  =  elem;
 64          }
 65           // set left child tree
 66           void  set_left(T  * left) {
 67             m_left  =  left;
 68          }
 69           // set right child tree
 70           void  set_right(T  * right) {
 71              m_right  =  right;
 72          }
 73 
 74       private :
 75          U m_elem;
 76          T  * m_left;
 77          T  * m_right;
 78  };
 79 
 80 
 81  template < typename T >
 82  class  BinaryTreeNode;
 83  template < typename T >
 84  class  BinaryTreeNode :  public  BinaryTreeNodeBase <  T, BinaryTreeNode < T >   >
 85  {
 86       public :
 87          typedef normal_node_tag node_category;
 88          BinaryTreeNode( const  T &  elem, BinaryTreeNode < T >   *  left  =  NULL, BinaryTreeNode < T >   *  right  =  NULL)
 89                  : BinaryTreeNodeBase <  T, BinaryTreeNode < T >   >  (elem, left, right){}
 90 
 91  };
 92 
 93 
 94  // BinaryTreeNode With Parent Pointer
 95  template < typename T >
 96  class  BinaryTreeNodeWPP :  public  BinaryTreeNodeBase <  T, BinaryTreeNodeWPP < T >   >
 97  {
 98       public :
 99          typedef with_parent_node_tag node_category;
100          BinaryTreeNodeWPP() : m_parent(NULL) {}
101          BinaryTreeNodeWPP( const  T &  elem, BinaryTreeNodeWPP < T >   *  left  =  NULL, BinaryTreeNodeWPP < T >   *  right  =  NULL,
102                            BinaryTreeNodeWPP < T >   * parent  =  NULL)
103                  : BinaryTreeNodeBase <  T, BinaryTreeNodeWPP < T >   >  (elem, left, right), m_parent(parent){}
104          BinaryTreeNodeWPP < T >   *  parent()  const  {
105               return  m_parent;
106          }
107           void  set_parent(BinaryTreeNodeWPP < T >   *  parent) {
108              m_parent  =  parent;
109               // this->set_right(NULL);     // test 见 effective c++ 模板条款43
110          }
111       private :
112          BinaryTreeNodeWPP < T >   * m_parent;
113  };
114 
115 
116  template < typename U, typename T >
117  class  BinaryTreeHelper
118  {
119       protected :
120           void  CreateTreeHelper(T  *& root, U end_mark); 
121          T *  AncestorHelper(T  * root, T  * p, T  * q);
122  };
123  template  < typename U, typename T >
124  void  BinaryTreeHelper < U, T > ::CreateTreeHelper(T  *& root, U end_mark)
125  {
126      U input;
127      cin  >>  input;
128       if  ( input  !=  end_mark )
129      {
130          root  =   new  T ( input );      // 注意new 的时候,默认就将->left,->right指针赋值为NULL了
131          CreateTreeHelper ( root -> m_left, end_mark );  // 如果函数这么写,用引用,则必然需要直接访问私有变量
132          CreateTreeHelper ( root -> m_right, end_mark );
133      }
134  }
//这个是按照后序遍历的思路求两个节点的最近公共祖先,感觉这个方法与递归比起来更省脑细胞一点。
135  template  < typename U, typename T >
136  *  BinaryTreeHelper < U,T > ::AncestorHelper(T  * root, T  * p, T  * q)
137  {
138       if  (p  ==  q)
139           return  p;
140       if  (p  ==  root  ||  q  ==  root)
141           return  root;
142      T  * pcur  =  root;
143      stack <  T  *   >  s;
144      stack < bool >  ss;         // 标示有没有进入右子树(是否是从右子树返回该节点)
145       int  find  =   0 ;
146       int  flag  =   0 ;
147      stack < bool >  fs;      // flag stack 标示是否是已经找到了第一个之后再入栈
148       while  ( ! s.empty()  ||  pcur ) {
149           if  (pcur) {
150              s.push(pcur);
151              ss.push( 0 );
152              fs.push(flag);           // well 这里代码顺序重要的,如果在后面,则当前这个的flag为1就出问题了,因为p,q可能本身就是所求最近祖先
153               if  (pcur  ==  p  ||  pcur  ==  q) {  // 如果定义不允许自身为自身的祖先,那么就应该把fs.push(flag)放在后面,这样会p->parent返回
154                  find ++ ;                      // 如果p是q的祖先的话
155                   if  (find  ==   1 )   // 我们找到了一个
156                      flag  =   1 ;
157                   else              // 找到两个
158                       break ;
159              }
160              pcur  =  pcur -> left();
161          }  else  {
162              pcur  =  s.top();
163               if  (ss.top()) {    
164                  s.pop();
165                  ss.pop();
166                  fs.pop();
167                  pcur  =  NULL;   
168              }  else  {
169                  ss.top()  =   1 ;
170                  pcur  =  pcur -> right();
171              }
172          }
173      }
174      assert(find  ==   2 );       // 如果没能够在二叉树中全部找到p,q,输入有误
175      assert( ! fs.empty());
176       while  (fs.top()) {
177          fs.pop();
178          s.pop();
179      }
180      assert( ! s.empty());
181       return  s.top();
182  }
183 
184  template < typename U >
185  class  BinaryTreeHelper <  U, BinaryTreeNodeWPP < U >   >
186  {
187       protected :
188           void  CreateTreeHelper( BinaryTreeNodeWPP < U >   *& root, U end_mark); 
189           BinaryTreeNodeWPP < U >   *  AncestorHelper(BinaryTreeNodeWPP < U >   * root,  
190                          BinaryTreeNodeWPP < U >   * p,  BinaryTreeNodeWPP < U >   * q);
191       private :
192           void  CreateTreeHelperKernal(BinaryTreeNodeWPP < U >   *& root,
193                          BinaryTreeNodeWPP < U >   * parent, U end_mark);
194           void  FindPath2Root( BinaryTreeNodeWPP < U >   * p, stack <  BinaryTreeNodeWPP < U >   *   >   & s); 
195  };
196  // 用户交互输入,建立3叉链表二叉树
197  template  < typename U >
198  void  BinaryTreeHelper <  U, BinaryTreeNodeWPP < U >   > ::CreateTreeHelper(BinaryTreeNodeWPP < U >   *& root, U end_mark)
199  {
200      CreateTreeHelperKernal ( root, NULL, end_mark );
201  }
202  template  < typename U >
203  void  BinaryTreeHelper <  U, BinaryTreeNodeWPP < U >   > ::CreateTreeHelperKernal(BinaryTreeNodeWPP < U >   *& root, 
204                                                      BinaryTreeNodeWPP < U >   * parent, U end_mark)
205  {
206      U input;
207      cin  >>  input;
208       if  (input  !=  end_mark) {
209          root  =   new  BinaryTreeNodeWPP < U > (input);       // notice we use BinaryTreeNode2
210          root -> set_parent(parent);
211          CreateTreeHelperKernal(root -> m_left, root, end_mark);  // 如果函数这么写,用引用,则必然需要直接访问私有变量
212          CreateTreeHelperKernal(root -> m_right, root, end_mark);
213      }
214  }
215  template  < typename U >
216  void  BinaryTreeHelper <  U, BinaryTreeNodeWPP < U >   > ::FindPath2Root(
217          BinaryTreeNodeWPP < U >   * p, stack <  BinaryTreeNodeWPP < U >   *>   & s) 
218  {
219      BinaryTreeNodeWPP < U >   *  q  =  p;
220       while  (q) {      // 根节点的父指针为NULL
221          s.push(q);
222          q  =  q -> parent();
223      }
224  }
225  template  < typename U >
226  BinaryTreeNodeWPP < U >   *  BinaryTreeHelper <  U, BinaryTreeNodeWPP < U >   > ::AncestorHelper(BinaryTreeNodeWPP < U >   * root, 
227                                                                      BinaryTreeNodeWPP < U >   * p, BinaryTreeNodeWPP < U >   *  q)
228  {
229      stack <  BinaryTreeNodeWPP < U >    *>   s1;
230      stack <  BinaryTreeNodeWPP < U >    *>   s2;
231      FindPath2Root(p, s1);
232      FindPath2Root(q, s2);
233      BinaryTreeNodeWPP < U >   * ancestor;
234       while  ( ! s1.empty()  &&   ! s2.empty()  &&  
235              (s1.top()  ==  s2.top())) {
236          ancestor  =  s1.top();
237          s1.pop();
238          s2.pop();
239      }
240       return  ancestor;
241  }
242 
243 
244  // 参数默认声明只能出现一次
245  template < typename U, typename T  =  BinaryTreeNode < U >   >
246  class  BinaryTree;
247 
248  //  TODO 这个BinaryTree太臃肿了,要把最基本的功能提出来
249  // template<typename U, typename T =  BinaryTreeNode<U> >
250  template < typename U, typename T >
251  class  BinaryTree :  public  SimpleBinaryTree < U, T > private  BinaryTreeHelper < U,T >
252  {
253       public :
254          template  < typename type1, typename type2 >  friend  class   BinaryTreeHelper;  // 要用到m_root
255           using  SimpleBinaryTree < U, T > ::m_root;
256           using  SimpleBinaryTree < U, T > ::root;
257           using  SimpleBinaryTree < U, T > ::left_child_of;
258           using  SimpleBinaryTree < U, T > ::right_child_of;
259           using  SimpleBinaryTree < U, T > ::IsEmpty;
260           using  SimpleBinaryTree < U, T > ::set_root;
261           // 如果改变一下三叉树建立函数,不用引用的化,left = Create.() 这样就可以不用私有变量
262          BinaryTree ( T  * root  =  NULL ) : SimpleBinaryTree < U, T > (root) {}
263 
264          T *  parent_of ( T  * current );
265           // 访问某节点 当前默认为输出该节点元素值
266           void  Visit ( T  * current )
267          {
268              cout  <<  current -> elem()  <<   "   " ;
269          }
270           void  VisitData (T  * current,  int  width)
271          {
272              cout  <<  setw(width)  <<  current -> elem();
273          }
274           // 删除二叉树或其子树
275           // virtual void DeleteBinaryTree (T *root );     
276           // 将给定的两个二叉树作为根的左子和右子树建立新的二叉树
277           void  CreateTree (  const  U  & elem, BinaryTree < U,T >   & left_tree, BinaryTree < U,T >   & right_tree );
278           // 先序遍历
279           void  PreOrderTravel ( T  * root );
280           void  PreOrderTravelNorec ( T  * root );
281           // 中序遍历
282           virtual   void  InOrderTravel ( T  * root );      // 这里可以改写为统一接口,函数参数位函数对象,选择不同的实现
283           virtual   void  InOrderTravelNorec ( T  * root );
284           // 后序遍历
285           void  PostOrderTravel ( T  * root );   //  TODO const  // void PostOrderTravel(const T *root) const
286           void  PostOrderTravelNorec ( T  * root );
287           // 广度优先按层次遍历,利用队列
288           void  LevelOrderTravel ( T  * root );
289           // 用户假定树中元素是唯一的,查找值为elem的节点,返回其指针,找不到返回NULL
290           // 如果存在多个,返回按照先序遍历找到的第一个
291          T  *  FindElem(T  * root, U elem);
292 
293           // 返回树的高度,例如只有一个根节点返回1,但根节点记录为层次0
294           int  Depth()  const ;
295           // 为了方便调试,按二叉树的形态将其简单打印出来,利用了层次遍历
296           // size假定输出的占位大小如size=2占两个空格,width_spacing两个节点之间的间隔
297           // width_spacing为2表示空2*size的距离
298           // 不包括节点的占位,height_sapcing,两个层次见的换行数目
299           // PrintTree函数会调用Detpth(),Detpth()会调用Depth(T *root)
300           // 在Depth(T *root)中会用到 TODO TODO traits 手法 TODO TODO
301           void  PrintTree ( const   int  size  =   3 const   int  width_spacing  =   1 ,
302                           const   int  height_spacing  =   2 );
303           // 下面是PKU2007实验班的作业3题目
304           // 3.1二叉树节点的值唯一,找出值为x的节点所在树中的层次
305           int  NodeLayer ( T  * root, U x );
306           // 3.2 给定前序和中序队列,生成二叉树,并打印后序队列
307           void  CreateTree ( vector < U >   & preorder_vec, vector < U >   & inorder_vec );
308           // 用户交互输入,生成二叉树,某个方向的输入结束由 end_mark 标记
309           virtual   void  CreateTree ( U end_mark );
310           // 同上的交互输入,但是凡是最后带2后缀的都表示是三叉链表表示
311           // void CreateTree2(U end_mark);
312           // 表达式二叉树专用函数,根据表达式二叉树,求得它的中缀表达式,结果存于 infix_string;
313           // TODO 像下面这些非kernal的特殊的功能不应该出现在这里,应该提出新的继承子类
314           void  ExpressionBinaryTree2infix ( T  * root,  string &  infix_string );
315           // 功能同上非递归
316           void  ExpressionBinaryTree2infixNoRec(T  * root,  string &  infix_string);
317           // 求两个给定节点p,q的最近祖先,分别用二叉树和三叉树实现
318          T  *  Ancestor(T  * p, T  *  q);
319           // 给出二叉树中距离最远的两个节点
320           // 思路,要麽是左子树的深度加上右子树的深度,要麽就是取左子树或者右子树的max distance(子问题).
321           // 递归过程,类似后序遍历,子问题先于根节点得出结果,关键要想到可用一个maxlen 保存当前最大值即可
322           // 不需要对于每个子树记录下它对应的max distance,然后再在根节点比较 左右子树和取根节点3种情况
323           // 的最大值
324           int  MaxDistance() {
325               int  maxlen  =   0 ;
326              find( this -> m_root, maxlen);
327               return  maxlen;
328          }
329           int  find(T  * root,  int   & maxlen) {
330               int  ldepth, rdepth;
331               if  (root -> left())
332                  ldepth  =  find(root -> left(), maxlen);
333               else
334                  ldepth  =   - 1 ;
335               if  (root -> right())
336                  rdepth  =  find(root -> right(), maxlen);
337               else
338                  rdepth  =   - 1 ;
339               int  depth;
340               if  (ldepth  >  rdepth)
341                  depth  =  ldepth  +   1 ;
342               else
343                  depth  =  rdepth  +   1 ;
344               if  ((ldepth  +  rdepth  +   2 >  maxlen)
345                  maxlen  =  ldepth  +  rdepth  +   2 ;
346               return  depth;
347          }
348 
349       private :
350           // DISALLOW_COPY_AND_ASSIGN ( BinaryTree );
351           int  Depth (T  * root)  const ;
352           int  Depth (T  * root, normal_node_tag)  const ;
353           int  Depth(T  * root, with_thread_node_tag)  const
354           void  PrintTree ( const   int  size,  const   int  width_spacing,
355                           const   int  height_spacing, normal_node_tag);
356           void  PrintTree ( const   int  size,  const   int  width_spacing,
357                           const   int  height_spacing, with_thread_node_tag);
358         
359           void  PrintSpace (  int  num  =   1  )
360          {
361               // cout << "\r";   // 回到行首
362               for  (  int  i  =   0 ; i  <  num; i ++  )
363                  cout  <<   "   " ;
364          }
365           void  PrintEmptyLine (  int  num  =   1  )
366          {
367               for  (  int  i  =   0 ; i  <  num; i ++  )
368                  cout  <<  endl;
369          }
370           // private util func for CreateTree(vector<T> &preorder_vec, vector<T> &inorder_vec)
371          T  *  CreateTreeKernal ( vector < U >   & preorder_vec, vector < U >   & inorder_vec,
372                                                  int  b1,  int  e1,  int  b2,  int  e2 );
373 
374           int  NodeLayerKernal ( T  * root, U x,  int  level );
375  :e
376  };
377 
378  // return parrent node of the current node
379  template < typename U, typename T >
380  T *  BinaryTree < U,T > ::parent_of ( T  * current )
381  {
382 
383  }
384 
385 
386  // 将给定的两个二叉树作为根的左子和右子树建立新的二叉树
387  template < typename U, typename T >
388  void  BinaryTree < U,T > ::CreateTree (  const  U  & elem, BinaryTree < U,T >   & left_tree, BinaryTree < U,T >   & right_tree )
389  {
390      m_root  =   new  T;
391      m_root -> set_elem ( elem );
392      m_root -> set_left ( left_tree.root() );
393      m_root -> set_right ( right_tree.root() );
394  }
395 
396 
397  // pre order travel
398  template < typename U, typename T >
399  void  BinaryTree < U,T > ::PreOrderTravel ( T  * root )
400  {
401       if  ( root )
402      {
403          Visit ( root );
404          PreOrderTravel ( root -> left() );
405          PreOrderTravel ( root -> right() );
406      }
407  }
408  template < typename U, typename T >
409  void  BinaryTree < U,T > ::PreOrderTravelNorec ( T  * root )
410  {
411      T  * =  root;
412      stack <  T  *   >  s;
413       while  ( ! s.empty()  ||  p) {
414           if  (p) {
415              Visit(p);                  // visit 
416              s.push(p);                 // 保留当前栈,以便左子树退出,利用当前栈信息进右子树
417              p  =  p -> left();
418          }  else  {                 //  if null return 对应左子树访问完进入右子树,或右子树访问完向上进入上一层右子树
419              p  =  s.top();               // 左子树退出  rec(left)   取出栈信息,进入右边 rec(right)
420              s.pop();                   // 当前栈没有用了,右子树完了,要向上访问上一个个栈信息,所以退栈
421              p  =  p -> right();
422          }
423      }
424  }
425 
426 
427  // in order travel
428  template < typename U, typename T >
429  void  BinaryTree < U,T > ::InOrderTravel ( T  * root )
430  {
431       if  ( root )
432      {
433          InOrderTravel ( root -> left() );
434          Visit ( root );
435          InOrderTravel ( root -> right() );
436      }
437  }
438 
439 
440 
441  template < typename U, typename T >
442  void  BinaryTree < U,T > ::InOrderTravelNorec ( T  * root )
443  {
444      T  * =  root;
445      stack <  T  *   >  s;
446 
447       while  ( ! s.empty()  ||  p) {
448           if  (p) {
449              s.push(p);
450              p  =  p -> left();
451          }  else  {
452              p  =  s.top();
453              Visit(p);
454              s.pop();
455              p  =  p -> right();
456          }
457      }
458   
459  }
460 
461  // post order travel
462  template < typename U, typename T >
463  void  BinaryTree < U,T > ::PostOrderTravel ( T  * root )
464  {
465       if  ( root )
466      {
467          PostOrderTravel ( root -> left() );
468          PostOrderTravel ( root -> right() );
469          Visit ( root );
470      }
471  }
472 
473  template < typename U, typename T >
474  void  BinaryTree < U,T > ::PostOrderTravelNorec ( T  * root )
475  {
476      T  * =  root;
477      stack <  T  *   >  s;
478      stack < bool >  ss;         // 标示有没有进入右子树(是否是从右子树返回该节点)
479       while  ( ! s.empty()  ||  p) {
480           if  (p) {
481              s.push(p);
482              ss.push( 0 );
483              p  =  p -> left();
484          }  else  {
485              p  =  s.top();
486               if  (ss.top()) {      // 右子树返回
487                  Visit(p);
488                  s.pop();
489                  ss.pop();
490                  p  =  NULL;    // 循环控制的需要,当根节点访问完,要向上继续退栈
491              }  else  {         // 左子树返回,将进入右子树,标记ss.top = 1
492                  ss.top()  =   1 ;
493                  p  =  p -> right();
494              }
495          }
496      }
497  }
498 
499 
500  // 注意该结构不涉及资源管理
501  // 所以用编译器默认给出的拷贝构造函数即可
502  template  < typename T >
503  class  LevelData
504  {
505       public :
506          LevelData ( T  * node  =  NULL,  int  level  =   0  ) : m_node ( node ), m_level ( level ) {}
507          T  *  node()  const
508          {
509               return  m_node;
510          }
511           int  level()  const
512          {
513               return  m_level;
514          }
515       private :
516          T  * m_node;
517           int  m_level;
518  };
519 
520 
521  // travel fowllow level bread first travel
522  template < typename U, typename T >
523  void  BinaryTree < U,T > ::LevelOrderTravel ( T  * root )
524  {
525      queue <  LevelData < T >   >  q;
526      q.push ( LevelData < T >  ( root, 0  ) );
527 
528       while  (  ! q.empty() )
529      {
530          LevelData < T >  current_data  =  q.front();
531          q.pop();
532          Visit ( current_data.node() );
533           if  ( current_data.node() -> left() )
534              q.push ( LevelData < T >  ( current_data.node() -> left(),current_data.level()  +   1  ) );
535           if  ( current_data.node() -> right() )
536              q.push ( LevelData < T >  ( current_data.node() -> right(),current_data.level()  +   1  ) );
537      }
538  }
539 
540  template  < typename T >
541  class  LevelPrintData :  public  LevelData < T >
542  {
543       public :
544          LevelPrintData ( T  * node  =  NULL,  int  level  =   0  ,  int  pos  =   0  ) :LevelData < T >  ( node, level ), m_pos ( pos ) {}
545           int  pos()  const
546          {
547               return  m_pos;
548          }
549       private :
550           int  m_pos;
551  };
552 
553  // 开始的方法思路是正确的但是忽略了输出字符要占位置至少一个空格
554  // spacing 是这样的 最底层的spacing最小
555  // spacing 一定是显示字符(所有的显示字符给于相同的占位如2个空格)
556  // 设字符占位为a
557  // 最底层 sapcing = a
558  // 则往上依次 spacing = 3a  spacing = 7a
559  // spacing = 2*spacing_pre+1
560  // 最底层width_spacing 取 1, 3, 5
561  // b 2b+1 2(2b+1)+1
562  // a0 = b a1 = 2a0 + 1 a2 = 4a0 + 2 + 1   an = 2^n*a0 + 2^n - 1 = 2^n(a0 + 1) - 1
563  // a0 level = depth -1
564  // a(depth -1) level = 0
565  // level + n = depth - 1
566  // n = depth - 1 - level
567  template < typename U, typename T >
568  void  BinaryTree < U,T > ::PrintTree( const   int  size,  const   int  width_spacing,
569                                   const   int  height_spacing) {
570       return  PrintTree(size, width_spacing, height_spacing, 
571                       typename node_traits < T > ::node_category());
572  }
573 
574  template < typename U, typename T >
575  void  BinaryTree < U,T > ::PrintTree( const   int  size,  const   int  width_spacing,
576                                   const   int  height_spacing, normal_node_tag)
577  {
578      assert(width_spacing  %   2   ==   1 );
579       if  (IsEmpty())
580           return ;
581       int  depth  =  Depth();
582       // 每层第一个节点相对于树的最左边起始位置的偏移量 init_spacing
583       int  node_num  =   1   <<  (depth  -   1 );      // 最底层的节点数目,按完全满二叉树算
584       int  init_spacing  =  (((node_num  -   1 *  width_spacing  +  node_num  -   1 /   2 *  size;
585      T  * =  root();
586       int  sum  =   0 ;
587       while (p -> left()) {
588          p  =  p -> left();
589          sum ++ ;
590      }
591       // 最左边高度为depth-sum的子树没有,可以将root的中心位置相应左移
592       int  node_num2  =   1   <<  (depth  -  sum  -   1 );
593       int  init_spacing2  =  (((node_num2  -   1 *  width_spacing  +  node_num2  -   1 /   2 *  size;
594      init_spacing  -=  init_spacing2;
595      
596      
597      queue <  LevelPrintData < T >   >  q;
598      q.push (LevelPrintData < T > (root(),  0 , init_spacing));
599 
600 
601       int  current_level  =   0 ;
602       // 每层中两个相邻节点的spacing  spacing_level
603       int  spacing_level  =  (( 1   <<  (depth  -   1   -  (current_level  +   1 )))  *  (width_spacing  +   1 -   1 *  size;
604       int  pre_pos  =   - 1 ;
605       int  move_num;
606       int  left_shift, right_shift;
607       while  ( ! q.empty()) {
608          LevelPrintData < T >  current_data  =  q.front();
609          q.pop();
610           if  (current_data.level()  >  current_level) {
611              PrintEmptyLine(height_spacing);
612              current_level  =  current_data.level();
613               // 是下一层的间距the spacing level for current_level + 1
614               // 对于最底层其实是不需要再求底下的spacing的,因为没有孩子了
615              spacing_level  =  (( 1   <<  (depth  -   1   -  (current_level  +   1 )))  *  (width_spacing  +   1 -   1 *  size;
616              pre_pos  =   - 1 ;
617          }
618           if  (pre_pos  ==   - 1 )   // 该层首个节点,原来程序pre_pos开始置为0,所以遇到首节点位置是0时出错,因为访问第二个的时候pre_pos还是0
619              move_num  =  current_data.pos();
620           else
621              move_num  =  current_data.pos()  -  pre_pos  -  size;
622          PrintSpace(move_num);
623          VisitData(current_data.node(), size);
624          pre_pos  =  current_data.pos();
625          left_shift  =  ((spacing_level / size  +   1 /   2 *  size;
626          right_shift  =  ((spacing_level / size  +   1 /   2 *  size;
627              if  (current_data.node() -> left())
628              q.push(LevelPrintData < T > (current_data.node() -> left(),current_data.level()  +   1 ,
629                                         current_data.pos()  -  left_shift));
630           if  (current_data.node() -> right())
631              q.push(LevelPrintData < T > (current_data.node() -> right(),current_data.level()  +   1 ,
632                                         current_data.pos()  +  right_shift));
633      }
634      cout  <<  endl;
635  }
636 
637  template < typename U, typename T >
638  void  BinaryTree < U,T > ::PrintTree( const   int  size,  const   int  width_spacing,
639                                   const   int  height_spacing, with_thread_node_tag)
640  {
641      cout  <<   " Using Triats method we are printing thread tree now "   <<  endl;
642      assert(width_spacing  %   2   ==   1 );
643       if  (IsEmpty())
644           return ;
645       int  depth  =  Depth();
646       // 每层第一个节点相对于树的最左边起始位置的偏移量 init_spacing
647       int  node_num  =   1   <<  (depth  -   1 );      // 最底层的节点数目,按完全满二叉树算
648       int  init_spacing  =  (((node_num  -   1 *  width_spacing  +  node_num  -   1 /   2 *  size;
649      T  * =  root();
650       int  sum  =   0 ;
651       while ( ! p -> ltag()) {
652          p  =  p -> left();
653          sum ++ ;
654      }
655       // 最左边高度为depth-sum的子树没有,可以将root的中心位置相应左移
656       int  node_num2  =   1   <<  (depth  -  sum  -   1 );
657       int  init_spacing2  =  (((node_num2  -   1 *  width_spacing  +  node_num2  -   1 /   2 *  size;
658      init_spacing  -=  init_spacing2;
659      
660      
661      queue <  LevelPrintData < T >   >  q;
662      q.push (LevelPrintData < T > (root(),  0 , init_spacing));
663 
664 
665       int  current_level  =   0 ;
666       // 每层中两个相邻节点的spacing  spacing_level
667       int  spacing_level  =  (( 1   <<  (depth  -   1   -  (current_level  +   1 )))  *  (width_spacing  +   1 -   1 *  size;
668       int  pre_pos  =   - 1 ;
669       int  move_num;
670       int  left_shift, right_shift;
671       while  ( ! q.empty()) {
672          LevelPrintData < T >  current_data  =  q.front();
673          q.pop();
674           if  (current_data.level()  >  current_level) {
675              PrintEmptyLine(height_spacing);
676              current_level  =  current_data.level();
677               // 是下一层的间距the spacing level for current_level + 1
678               // 对于最底层其实是不需要再求底下的spacing的,因为没有孩子了
679              spacing_level  =  (( 1   <<  (depth  -   1   -  (current_level  +   1 )))  *  (width_spacing  +   1 -   1 *  size;
680              pre_pos  =   - 1 ;
681          }
682           if  (pre_pos  ==   - 1 )   // 该层首个节点,原来程序pre_pos开始置为0,所以遇到首节点位置是0时出错,因为访问第二个的时候pre_pos还是0
683              move_num  =  current_data.pos();
684           else
685              move_num  =  current_data.pos()  -  pre_pos  -  size;
686          PrintSpace(move_num);
687          VisitData(current_data.node(), size);
688          pre_pos  =  current_data.pos();
689          left_shift  =  ((spacing_level / size  +   1 /   2 *  size;
690          right_shift  =  ((spacing_level / size  +   1 /   2 *  size;
691              if  ( ! current_data.node() -> ltag())
692              q.push(LevelPrintData < T > (current_data.node() -> left(),current_data.level()  +   1 ,
693                                         current_data.pos()  -  left_shift));
694           if  (current_data.node() -> right()  &&   ! current_data.node() -> rtag())
695              q.push(LevelPrintData < T > (current_data.node() -> right(),current_data.level()  +   1 ,
696                                         current_data.pos()  +  right_shift));
697      }
698      cout  <<  endl;
699  }
700 
701  template < typename U, typename T >
702  int  BinaryTree < U,T > ::Depth (T  * root)  const  
703  {
704       // TODO TODO 这样的局限性是没有一个默认的函数,即使普通Node也
705       // 需要:Depth ( T *root, normal_node_tag )
706       return  Depth(root,typename node_traits < T > ::node_category());
707  }
708 
709  template < typename U, typename T >
710  int  BinaryTree < U,T > ::Depth ( T  * root, normal_node_tag )  const
711  {
712       if  (root) {
713           int  depth_left  =  Depth (root -> left());
714           int  depth_right  =  Depth (root -> right());
715           return  depth_left  >  depth_right   ?  depth_left  +   1  : depth_right  +   1 ;
716      }
717       else
718           return   0 ;
719  }
720 
721  template < typename U, typename T >
722  int  BinaryTree < U,T > ::Depth(T  * root, with_thread_node_tag)  const  
723  {
724          if  (root) {
725           int  depth_left, depth_right;
726           if  ( ! root -> ltag())
727               // 错误: expected primary-expression before ‘)’ token why?
728               // depth_left = Depth(root->left(), with_thread_node_tag);
729              depth_left  =  Depth(root -> left());
730           else
731              depth_left  =   0 ;
732          
733           if  ( ! root -> rtag())
734              depth_right  =  Depth(root -> right());
735           else
736              depth_right  =   0 ;
737           return  depth_left  >  depth_right   ?  depth_left  +   1  : depth_right  +   1 ;
738      }
739  }
740 
741 
742  template < typename U, typename T >
743  int  BinaryTree < U,T > ::Depth()  const
744  {
745       return  Depth ( m_root );
746  }
747 
748  template < typename U, typename T >
749  int  BinaryTree < U,T > ::NodeLayerKernal ( T  * root, U x,  int  level )
750  {
751       if  ( root )
752      {
753           if  ( root -> elem()  ==  x )
754               return  level;
755           else
756          {
757               int  level_left  =  NodeLayerKernal ( root -> left(), x, level  +   1  );
758               if  ( level_left  !=   - 1  )
759                   return  level_left;
760               int  level_right  =  NodeLayerKernal ( root -> right(), x, level  +   1  );
761               if  ( level_right  !=   - 1  )
762                   return  level_right;
763               return   - 1 ;
764          }
765      }
766       else
767           return   - 1 ;
768  }
769  template < typename U, typename T >
770  int  BinaryTree < U,T > ::NodeLayer ( T  * root, U x )
771  {
772       return  NodeLayerKernal ( root, x,  0  );
773  }
774 
775  template < typename U, typename T >
776  *  BinaryTree < U,T > ::FindElem(T  * root, U elem)
777  {
778       if ( ! root)
779           return  NULL;     // well 递归返回点 这个不能忘阿 切记,再说没有下面root->elem会段错误的
780       if  (root -> elem()  ==  elem)
781           return  root;
782      T  * =  FindElem(root -> left(), elem);
783       if  (p)
784           return  p;
785      p  =  FindElem(root -> right(), elem);
786       if  (p)
787           return  p;
788       return  NULL;
789  }
790 
791  template < typename U, typename T >
792  void  BinaryTree < U,T > ::CreateTree ( vector < U >   & preorder_vec, vector < U >   & inorder_vec )
793  {
794      assert ( preorder_vec.size()  >   0   &&  inorder_vec.size()  ==  preorder_vec.size() );
795      m_root  =  CreateTreeKernal ( preorder_vec, inorder_vec,  0 , preorder_vec.size()  -   1 0 , inorder_vec.size()  -   1  );
796  }
797 
798  // private util func for CreateTree(vector<T> &preorder_vec, vector<T> &inorder_vec)
799  // b1,e1 分别表示当前子树,先序队列的顺序,在preoder_vec中的起始和终止坐标
800  // b2,e2, 类似 表示中序的,inorder_vec的起始终止坐标
801  template < typename U, typename T >
802  *  BinaryTree < U,T > ::CreateTreeKernal ( vector < U >   & preorder_vec, vector < U >   & inorder_vec,
803           int  b1,  int  e1,  int  b2,  int  e2 )
804  {
805      T  *  root  =   new  T (preorder_vec[b1]);    // we find the root elem
806 
807       int  i  =  b2;
808       int  len  =   0 ;
809 
810       // to find preorder_vec[b1] in inorder_vec   寻找中序中根节点的位置
811       while  ( inorder_vec[i]  !=  preorder_vec[b1] )
812      {
813          i ++ ;
814          len ++ ;
815      }
816 
817       if  ( i  !=  b2 )   // 如果存在左子树,需要生成左子树,注意如果 b1 == e1 即数组大小为1,两个if都会失败,直接返回root
818          root  -> set_left ( CreateTreeKernal ( preorder_vec, inorder_vec, b1  +   1 , b1  +  len, b2, i  -   1  ) );   // b1 + 1 + (len - 1)
819       if  ( i  !=  e2 )
820          root -> set_right ( CreateTreeKernal ( preorder_vec, inorder_vec,b1  +  len  +   1 , e1, i  +   1 , e2 ) );
821 
822       return  root;
823  }
824  template < typename U, typename T >
825  void  BinaryTree < U,T > ::CreateTree ( U end_mark )
826  {
827       // CreateTreeKernal ( m_root, end_mark );
828       this -> CreateTreeHelper(m_root, end_mark);
829  }
830 
831  //  TODO temparay comment
832  //  新建一个namespace为这些help函数,防止在别的也是
833  //  binary_tree空间下的文件会出现冲突,另外
834  //  用的时候using namspace binary_tree_expression_help
835  //  在函数里面用,如果在外面,就又把整个binary_tree_expression_help
836  // 空间引入binary_tree空间了
837  namespace  binary_tree_expression_help {
838  enum  State{op,num};
839 
840  template  < typename T >
841  State Status ( T  * current )
842  {
843       if  ( current -> IsLeaf() )  // 叶节点必然是数字
844           return  num;
845       else
846           return  op;
847  }
848 
849  template  < typename T >
850  int  Priority ( T  * current )
851  {
852       if  (Status(current)  ==  num)    
853           return   2 ;
854       if  ( ( current -> elem() ) [ 0 ==   ' + '   ||  ( current -> elem() ) [ 0 ==   ' - '  )
855           return   0 ;
856       else                  //  * or /  with higher priority
857           return   1 ;
858  }
859 
860  template  < typename T >
861  int  Priority ( T elem )
862  {
863       if  ( elem[ 0 ==   ' + '   ||  elem[ 0 ==   ' - '  )
864           return   0 ;
865       else                  //  * or /  with higher priority
866           return   1 ;
867  }
868 
869  //  end of namespace  binary_tree_expression_help
870 
871  template < typename U, typename T >
872  void   BinaryTree < U,T > ::ExpressionBinaryTree2infix ( T  * root,  string &  infix_string )
873  {
874       using   namespace  binary_tree_expression_help;
875      assert ( Status ( root )  ==  op );
876       // 打印左子树
877       if  ( Status ( root -> left() )  ==  num )
878          infix_string.append ( root -> left() -> elem() );
879       else
880      {
881           if  ( Priority ( root -> elem() )  >  Priority ( root -> left() -> elem() ) )
882              infix_string.append (  string  (  " ( "  ) );
883          ExpressionBinaryTree2infix ( root -> left(), infix_string );
884           if  ( Priority ( root -> elem() )  >  Priority ( root -> left() -> elem() ) )
885              infix_string.append (  string  (  " ) "  ) );
886      }
887       // 打印根节点
888      infix_string.append ( root -> elem() );
889       // 打印右子树
890       if  ( Status ( root -> right() )  ==  num )
891          infix_string.append ( root -> right() -> elem() );
892       else
893      {
894           if  ( Priority ( root -> elem() )  >=  Priority ( root -> right() -> elem() ) )
895              infix_string.append (  string  (  " ( "  ) );
896          ExpressionBinaryTree2infix ( root -> right(), infix_string );
897           if  ( Priority ( root -> elem() )  >=  Priority ( root -> right() -> elem() ) )
898              infix_string.append (  string  (  " ) "  ) );
899      }
900  }
901 
902  template < typename U, typename T >
903  void  BinaryTree < U,T > ::ExpressionBinaryTree2infixNoRec(T  * root,  string &  infix_string)
904  {
905       using   namespace  binary_tree_expression_help;
906      infix_string.clear();
907      T  * =  root;
908      stack <  T  *   >  s;
909      stack < bool >  s2;      // 后序遍历需要的标志位,开始为0,进入右子树则标记为1
910      stack < bool >  s3;
911      stack < bool >  s4;
912       bool  flag  =   0 ;   // flag用来标识,当左右子树即根都访问完,向上退栈的情况 
913       // 利用了后序非递归遍历的主框架
914       while  ( ! s.empty()  ||  (Status(p)  ==  op  &&   ! flag)) {
915           if  (Status(p)  ==  op  &&   ! flag) {
916              s.push(p);
917              s2.push( 0 );
918               if  (Priority(p)  >  Priority(p -> left())) {
919                  infix_string.append( " ( " );
920                  s3.push( 1 );
921              }  else  
922                  s3.push( 0 );
923              p  =  p -> left();
924          }  else  {
925               if  ( ! flag)
926                  infix_string.append(p -> elem());
927               else
928                  flag  =   0 ;
929              p  =  s.top();
930               if  ( ! s2.top()) {
931                   if  (s3.top())
932                      infix_string.append( string ( " ) " ));   // 左子树归来且需要)
933                  s3.pop();
934 
935                  infix_string.append(p -> elem());
936                  s2.top()  =   1 ;
937                   if  (Priority(p)  >=  Priority(p -> right())) {
938                      infix_string.append( " ( " );
939                      s4.push( 1 );                    
940                  }  else  
941                      s4.push( 0 );
942                  p  =  p -> right();
943              }  else  {
944                   if  (s4.top())
945                      infix_string.append( string ( " ) " ));    // 右子树归来且需要)
946                  s4.pop();
947 
948                  s.pop();
949                  s2.pop();
950                  flag  =   1 ;    // 注意这里的循环控制,要向上退栈,但是这个时候只要栈为空 s.empty 程序就应该结束了
951              }                // 所以在循环控制上 + Status(p) == op && !flag
952          }
953      }
954   
955  }
956 
957  // pku hw 3 3.4
958  template < typename U, typename T >
959  *  BinaryTree < U,T > ::Ancestor(T  * p, T  *  q)
960  {
961       // AncestorKernal(m_root, p, q);
962       return   this -> AncestorHelper(m_root, p, q);
963  }
964 
965  // 数组二叉树找最近共同祖先
966  void  FindPath2Root( int  x,stack < int >   & s);
967  int  NearestAncestor( int  p,  int  q);
968 
969  //  end of namespace binary_tree
970  #endif    // end of _BINARY_TREE_NODE_H
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值