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