1 import java.util.LinkedList;
2 import java.util.Queue;
3 import java.util.Stack;
4
5 public class BST <E extends Comparable>{
6
7 private class Node{
8 public E e;
9 public Node left,right;
10
11 public Node(E e){
12 this.e=e;
13 left=null;
14 right=null;
15 }
16 }
17
18 private Node root;
19 private int size;
20
21 public BST(){
22 root=null;
23 size=0;
24 }
25
26 //向二分搜索树添加新元素
27 public void add(E e){
28 root=add(root,e);
29 }
30
31 //向以node为根的二分搜索树中插入元素E,递归算法
32 //返回插入新节点后二分搜索树的根
33 private Node add(Node node,E e){
34 if (node==null){
35 size++;
36 return new Node(e);
37 }
38
39 if (e.compareTo(node.e)<0)
40 node.left=add(node.left,e);
41 else if (e.compareTo(node.e)>0)
42 node.right=add(node.right,e);
43
44 return node;
45 }
46
47 public int size(){
48 return size;
49 }
50
51 public boolean isEmpty(){
52 return size==0;
53 }
54
55 //看二分搜索树是否包含元素e
56 public boolean contain(E e){
57 return contains(root,e);
58 }
59
60
61 //看以node为根的二分搜索树是否包含元素e,递归算法
62 private boolean contains(Node node,E e){
63 if (node==null)
64 return false;
65 if (e.compareTo(node.e)==0)
66 return true;
67 else if (e.compareTo(node.e)<0)
68 return contains(node.left,e);
69 else
70 return contains(node.right,e);
71 }
72
73 //二分搜索树的前序遍历
74 public void preOrder(){
75 preOrder(root);
76 }
77
78 //前序遍历以node为根的二分搜索树,递归算法
79 private void preOrder(Node node){
80 if (node==null)
81 return;
82
83 System.out.println(node.e);
84 preOrder(node.left);
85 preOrder(node.right);
86 }
87
88 //二分搜索树的非递归前序遍历-----比递归实现复杂(中序遍历和后序遍历非递归实现比前序遍历更难)
89 public void preOrderNR(){
90 Stack<Node>stack=new Stack<>();
91 stack.push(root);
92 while (!stack.isEmpty()){
93 Node cur=stack.pop();
94 System.out.println(cur.e);
95
96 if (cur.right!=null)
97 stack.push(cur.right);
98 if (cur.left!=null)
99 stack.push(cur.left);
100 }
101 }
102
103 //二分搜索树的中序遍历
104 public void inOrder(){
105 inOrder(root);
106 }
107
108 //中序遍历以node为根的二分搜索树,递归算法
109 private void inOrder(Node node){
110 if (node==null)
111 return;
112
113 inOrder(node.left);
114 System.out.println(node.e);
115 inOrder(node.right);
116 }
117
118 //二分搜索树的后序遍历-----应用: 为二分搜索树释放内存
119 public void postOrder(){
120 postOrder(root);
121 }
122
123 //后序遍历以node为根的二分搜索树,递归算法
124 private void postOrder(Node node){
125 if (node==null)
126 return;
127
128 postOrder(node.left);
129 postOrder(node.right);
130 System.out.println(node.e);
131 }
132
133 //二分搜索树的层序遍历
134 //广度优先遍历的意义:
135 //1. 更快的找到问题的解. 常用于算法设计中-最短路径
136 //2. 图的深度优先遍历和广度优先遍历
137 public void levelOrder(){
138 Queue<Node>q=new LinkedList<>();
139 q.add(root);
140 while (!q.isEmpty()){
141 Node cur=q.remove();
142 System.out.println(cur.e);
143
144 if (cur.left!=null)
145 q.add(cur.left);
146 if (cur.right!=null)
147 q.add(cur.right);
148 }
149 }
150 //寻找二分搜索树的最小元素
151 public E minimum(){
152 if (size==0)
153 throw new IllegalArgumentException("BST is empty");
154
155 return minimum(root).e;
156 }
157
158 //返回以node为根的二分搜索树的最小值所在的节点
159 private Node minimum(Node node){
160 if (node.left==null)
161 return node;
162 return minimum(node.left);
163 }
164
165 //寻找二分搜索树的最大元素
166 public E maximum(){
167 if (size==0)
168 throw new IllegalArgumentException("BST is empty");
169
170 return maximum(root).e;
171 }
172
173 //返回以node为根的二分搜索树的最小值所在的节点
174 private Node maximum(Node node){
175 if (node.right==null)
176 return node;
177 return maximum(node.right);
178 }
179
180 @Override
181 public String toString(){
182 StringBuilder res=new StringBuilder();
183 generateBSTString(root,0,res);
184 return res.toString();
185 }
186
187 //从二分搜索树中删除最小值所在节点, 返回最小值
188 public E removeMin(){
189 E ret=minimum();
190 root=removeMin(root);
191 return ret;
192 }
193
194 //删除掉以node为根的二分搜索树中的最小节点
195 //返回删除节点后新的二分搜索树的根
196 private Node removeMin(Node node){
197 if (node.left==null){
198 Node rightNode=node.right;
199 node.right=null;
200 size--;
201 return rightNode;
202 }
203
204 node.left=removeMin(node.left);
205 return node;
206 }
207
208 //从二分搜索树中删除最大值所在节点
209 public E removeMax(){
210 E ret=minimum();
211 root=removeMax(root);
212 return ret;
213 }
214
215 //删除掉以node为根的二分搜索树中的最大节点
216 //返回删除节点后新的二分搜索树的根
217 private Node removeMax(Node node){
218 if (node.right==null){
219 Node leftNode=node.left;
220 node.right=null;
221 size--;
222 return leftNode;
223 }
224
225 node.right=removeMax(node.right);
226 return node;
227 }
228
229 //生成以node为根节点,深度为depth的描述二叉树的字符串
230 private void generateBSTString(Node node,int depth,StringBuilder res){
231 if (node==null){
232 res.append(generateDepthString(depth)+"null\n");
233 return;
234 }
235
236 res.append(generateDepthString(depth)+node.e+"\n");
237 generateBSTString(node.left,depth+1,res);
238 generateBSTString(node.right,depth+1,res);
239 }
240
241 //从二分搜索树删除掉元素为e的节点
242 public void remove(E e){
243 root=remove(root,e);
244 }
245
246 //删除以node为根的二分搜索树中值为e的节点,递归算法
247 //返回删除节点后新的二分搜索树的根
248 private Node remove(Node node,E e){
249 if (node==null)
250 return null;
251 if (e.compareTo(node.e)<0){
252 node.left=remove(node.left,e);
253 return node;
254 }else if (e.compareTo(node.e)>0){
255 node.right=remove(node.right,e);
256 return node;
257 }else { //e==node.e
258
259 //待删除节点左子树为空的情况
260 if (node.left==null){
261 Node rightNode=node.right;
262 node.right=null;
263 size--;
264 return rightNode;
265 }
266
267 //待删除节点右子树为空的情况
268 if (node.right==null){
269 Node leftNode=node.left;
270 node.left=null;
271 size--;
272 return leftNode;
273 }
274
275 //待删除节点左右子树均不为空的情况
276 //找到比待删除节点大的最小节点, 即待删除节点右子树的最小节点
277 //用这个节点顶替待删除节点的位置
278 Node successor=minimum(node.right);
279 successor.right=removeMin(node.right);
280 successor.left=node.left;
281
282 node.left=node.right=null;
283
284 return successor;
285 }
286 }
287
288 private String generateDepthString(int depth){
289 StringBuilder res=new StringBuilder();
290 for (int i=0;i<depth;i++)
291 res.append("--");
292 return res.toString();
293 }
294
295 }