您的位置:首页 > 其它

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

2009-08-30 14:07 405 查看
一般都是将节点数据类型作为二叉树模板的参数,这里尝试使用将节点类型直接作为二叉树的模板参数,例如一棵二叉树可以装配普通的二叉树节点,也可以装配带有父指针的三叉链表节点,或者装配线索二叉树节点。只是作为尝试,其实也许直接定义三叉链表二叉树,线索二叉树的设计更好。另外尝试了使用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 == 2) return NULL; // 忽略后面的遍历

if (root->leftchild()) {

isinleft = found;

if (ptr = Ancestor(root->leftchild(), p, q)) return ptr; // 左子树中找到p、q

isinleft = found - isinleft; // 是否左子树有一个目标节点

if (isroot && isinleft) return root; // 左子树中找到一个,根也是其中一个

}

if (found == 2) return NULL; // 忽略后面的遍历,chg add这个剪枝很强...

if (root->rightchild()) {

isinright = found;

if (ptr = Ancestor(root->rightchild(), p, q)) return ptr; // 右子树中找到p、q

isinright = found - isinright; // 是否右子树有一个目标节点

if ((isroot || isinleft) && isinright) return root; // 左右子树各一个,或右子树一个根也是一个

}

return NULL; // 不能在该子树中同时找到p和q

}


//下面的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 T * 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 T * 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 T * 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

if (isinroot && isinleft) //find one in root one left

return root;

}

if (found == 2)

return NULL;

if (root->right()) {

isinright = found;

if (ptr = AncestorHelperRec1Helper(root->right(), p, q, found)) //find p,q in right sub tree

return ptr;

isinright = found - isinright; //mark if we find one in right

if ((isinroot || isinleft) && isinright) //find one left and one right or find one in root and one right

return root;

}

return NULL;

}

//按后序遍历的思路,但是采用递归

template <typename U, typename T>

T * BinaryTreeHelper<U,T>::AncestorHelperRec2Helper(T *root, T *p, T *q, int &found, bool flag)

{

if (root == p || root == q)

found++;

if (found == 2) return NULL;

int next_flag = 0;

if (found == 1)

next_flag = 1; //此后的状态,已经找到一个之后再入栈了

T *ptr;

if (root->left()) {

if (ptr = AncestorHelperRec2Helper(root->left(), p, q, found, next_flag))

return ptr;

}

if (found == 2) {

if (!flag)

return root;

else

return NULL;

}

if (found == 1)

next_flag = 1;

if (root->right()) {

if (ptr = AncestorHelperRec2Helper(root->right(), p, q, found, next_flag))

return ptr;

}

if (!flag && found == 2)

return root;

else

return NULL;

}



//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 T * 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 *p = 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 *p = 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 *p = 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 *p = 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 *p = 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 T * 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 *p = 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 T * 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 *p = 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 T * 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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐