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


         一般都是将节点数据类型作为二叉树模板的参数,这里尝试使用将节点类型直接作为二叉树的模板参数,例如一棵二叉树可以装配普通的二叉树节点,也可以装配带有父指针的三叉链表节点,或者装配线索二叉树节点。只是作为尝试,其实也许直接定义三叉链表二叉树,线索二叉树的设计更好。另外尝试了使用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 = 3const 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() - 10, 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
  • 相关阅读:
    jquery模拟刮刮乐
    jq默认选中每项第一个
    让一个div水平且垂直居中
    ES6模块的import和export用法总结
    linux 标准目录
    spring 注解配置
    多线程下的两种单例写法
    java版二叉树算法实现
    JAVA版A星算法实现
    对于宫格地图寻最短路径的一个广度搜索算法
  • 原文地址:https://www.cnblogs.com/rocketfan/p/1556662.html
Copyright © 2020-2023  润新知