数据结构与算法(5): 树形结构-二叉查找树

性质

  • 若左子树不为空,则左子树上所有节点的值均小于它的根节点的值;
  • 若右子树不为空,则右子树上所有节点的值均大于它的根节点的值。
  • 左、右子树也分别为二叉查找树

实现

下面的实现代码中,insert和remove是通过递归实现的,之后用while语句替代对比一下。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
/**
* 二叉查找树
*/
public class BinarySearchTree<T extends Comparable<? super T>> {
private BinaryNode<T> root;
public BinarySearchTree() {
this.root = null;
}
/**
* 前序遍历
* 1. 访问根节点
* 2. 先序遍历左子树
* 3. 先序遍历右子树
*/
public void preOrder(){
preOrder(root);
System.out.println();
}
private void preOrder(BinaryNode<T> node){
if (node != null){
System.out.print(node.element + " ");
preOrder(node.left);
preOrder(node.right);
}
}
/**
* 中序遍历
* 1. 中序遍历左子树
* 2. 访问根节点
* 3. 中序遍历右子树
*/
public void inOrder(){
inOrder(root);
System.out.println();
}
private void inOrder(BinaryNode<T> node){
if (node != null){
inOrder(node.left);
System.out.print(node.element + " ");
inOrder(node.right);
}
}
/**
* 后序遍历
* 1. 后序遍历左子树
* 2. 后序遍历右子树
* 3. 访问根节点
*/
public void postOrder(){
postOrder(root);
System.out.println();
}
private void postOrder(BinaryNode<T> node){
if (node != null){
postOrder(node.left);
postOrder(node.right);
System.out.print(node.element + " ");
}
}
/**
* 插入
* @param ele
*/
public void insert(T ele){
root = insert(ele, root);
}
public void remove(T ele){
root = remove(ele, root);
}
/**
* 是否包含某元素
*
* @param ele
* @return
*/
public boolean contains(T ele) {
return contains(ele, root);
}
/**
* 清空树
*/
public void makeEmpty() {
root = null;
}
/**
* 判断空
*
* @return
*/
public boolean isEmpty() {
return root == null;
}
public void print(){
if (root != null){
print(root, root.element, 0);
}
}
/**
* @param node 打印的节点
* @param ele ele 父节点的值
* @param direction 0:根节点;-1:父节点的左儿子节点;1:父节点的右儿子节点
*/
private void print(BinaryNode<T> node, T ele, int direction){
if (node != null){
if (direction == 0){
System.out.printf("%s是根节点\n", ele);
}else {
System.out.printf("%s是%s的%s儿子节点\n", node.element, ele, direction==-1?"left":"right");
}
print(node.left, node.element, -1);
print(node.right, node.element, 1);
}
}
/**
* @param ele
* @param node
* @return 返回子树node的新的根节点
*/
private BinaryNode<T> insert(T ele, BinaryNode<T> node) {
if (node == null) {
return new BinaryNode<T>(ele);
}
int cmpResult = ele.compareTo(node.element);
if (cmpResult < 0) {
node.left = insert(ele, node.left);
} else if (cmpResult > 0) {
node.right = insert(ele, node.right);
} else {
// 插入的元素重复
System.out.println("INFO: duplicated element");
}
return node;
}
/**
* 删除节点时, 需要考虑该节点是有一个还是两个子树
*
* @param ele
* @param node
* @return 返回子树node的新的根节点
*/
private BinaryNode<T> remove(T ele, BinaryNode<T> node) {
if (node == null) {
// Element not found, do nothing
return null;
}
int cmpResult = ele.compareTo(node.element);
if (cmpResult < 0) {
node.left = remove(ele, node.left);
} else if (cmpResult > 0) {
node.right = remove(ele, node.right);
} else if (node.left != null && node.right != null) {
// 该节点有两个子树, 取右子树的最小元填充此节点
node.element = findMin(node.right).element;
node.right = remove(node.element, node.right);
} else {
// 该节点只有一个子树, 直接调整子树到填补该节点位置
node = (node.left != null) ? node.left : node.right;
}
return node;
}
private boolean contains(T ele, BinaryNode<T> node) {
if (node == null) {
return false;
}
int cmpResult = ele.compareTo(node.element);
if (cmpResult < 0) {
return contains(ele, node.left);
} else if (cmpResult > 0) {
return contains(ele, node.right);
} else {
return true;
}
}
private BinaryNode<T> findMin(BinaryNode<T> node) {
if (node == null) {
return null;
} else if (node.left == null) {
return node;
}
return findMin(node.left);
}
private BinaryNode<T> findMax(BinaryNode<T> node) {
if (node == null) {
return null;
} else if (node.right == null) {
return node;
}
return findMax(node.right);
}
private static class BinaryNode<T> {
T element;
BinaryNode<T> left;
BinaryNode<T> right;
BinaryNode(T element) {
this(element, null, null);
}
BinaryNode(T element, BinaryNode<T> left, BinaryNode<T> right) {
this.element = element;
this.left = left;
this.right = right;
}
}
}