-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathBinarySearchTree.java
349 lines (287 loc) · 8.12 KB
/
BinarySearchTree.java
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
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
package rsn170330.sp04;
import java.util.Iterator;
import java.util.Scanner;
import java.util.Stack;
import java.util.Comparator;
/**
* CS 5V81.001: Implementation of DSA
* Short Project 04: Implementation of Binary Search Tree
*
* @author Rahul Nalawade - rsn170330
* @author Bharath Reddy - bxr180008
*/
public class BinarySearchTree<T extends Comparable<? super T>> implements Iterable<T> {
// Standard Attributes of BST:
Entry<T> root; // root of BST
int size; // size of BST
// Personal Attributes of BST:
Entry<T> t; // a temporary entry
// to keep track of ancestral information -
// For tree-traversal from root to a certain node t
// useful in methods: find(t) bypass(t)
Stack<Entry <T>> ancestors = new Stack<Entry <T>>(); // also useful in AVL (balancing)
// Every node of BST = an Entry
public static class Entry<T> {
T element; // value of the entry
Entry<T> left, right; // left and right child
// default constructor
public Entry(T x, Entry<T> left, Entry<T> right) {
element = x;
this.left = left;
this.right = right;
}
// for internal use: Entry without any children
private Entry(T x) {
element = x;
left = null;
right = null;
}
}
// default constructor
public BinarySearchTree() {
root = null;
size = 0;
}
/**
* finds an entry that has its element = x. or
* finds an entry at which we failed to find x.
* @param x the element to be searched
* @return the Entry e where e.element = x
*/
private Entry<T> find(T x) {
ancestors.push(null); // pushing parent of root
return find(root, x);
}
/**
* O(depth(x)) worst case O(log n)
* Helper find(x) method: starts the search of x
* from the tree rooted at t (generally root)
* @param t the Entry from which the search begins
* @param x the element to be searched
* @return the Entry when search ends, when element = x is found
*/
private Entry<T> find(Entry<T> t, T x) {
// When first entry itself = null or when we found the element
if (t == null || t.element.equals(x)) return t;
//
while(true) {
// When x < t.element
if (x.compareTo(t.element) < 0) {
// When there is no left subtree
if (t.left == null) break; // when failed, return the element where failed
else {
// when left child exists
ancestors.push(t);
t = t.left;
}
}
// When t.element < x
else if (x.compareTo(t.element) > 0) {
if (t.right == null) break;
else {
ancestors.push(t);
t = t.right;
}
}
// We found the element
else break;
}
return t;
}
/**
* Is x contained in tree?
* @param x
* @return
*/
public boolean contains(T x) {
t = find(x);
if (t == null || x.compareTo(t.element) != 0) return false; // When failed
return true;
}
/**
* Is there an element that is equal to x in the tree?
* Element in tree that is equal to x is returned, null otherwise.
* @param x the element we are looking for
* @return if found, return the element, null otherwise
*/
public T get(T x) {
t = find(x);
if (t == null || x.compareTo(t.element) != 0) return null; // When not found
return x;
}
/**
* Add x to tree. If tree contains a node with same key, replace element by x.
* Returns true if x is a new element added to tree.
* @param x the element to be added
* @return is addition successful?
*/
public boolean add(T x) {
// When the tree itself is empty, DON'T attempt to find(x)
if (size == 0) {
root = new Entry<T>(x);
// Having dummy root node is not common in tree, unlike lists
size = 1;
}
else {
t = find(x); // t won't be null, as size > 0
if (x.compareTo(t.element) == 0) {
t.element = x; // replacement*
return false; // funny code :)
}
// Now, adding as child of t
else if (x.compareTo(t.element) < 0) t.left = new Entry<T>(x); // x < t.element
else t.right = new Entry<T>(x); // t.element < x
size++;
}
// addition successful
return true;
}
/**
* Remove x from tree. Return x if found, otherwise return null
* @param x the element to be removed
* @return removed element
*/
public T remove(T x) {
// When tree is empty
if (root == null) return null;
t = find(x);
// When we didn't found x in the tree
if (x.compareTo(t.element) != 0) return null;
T result = t.element; // found x at t
// When t has at-most one child.
if (t.left == null || t.right == null) bypass(t);
// When t has two children
else {
ancestors.push(t);
//attempting to find x which is at t in subtree rooted at t.right
Entry<T> minRight = find(t.right, x); // minimum RIGHT DESCENDANT of t*
t.element = minRight.element;
bypass(minRight); // minRight would always have at-most ONE child :)
}
size--;
return result;
}
// Returns minimum element in BST
public T min() {
if (size == 0) return null;
t = root; // starting at root
while (t.left != null) t = t.left; // tracing left subtree
return t.element;
}
// Returns maximum element in BST
public T max() {
if (size == 0) return null;
t = root; // starting at root
while (t.right != null) t = t.right; // tracing right subtree
return t.element;
}
/**
* Removes parent from the subtree -grandParent-parent-child-
* attaching only child to grandParent
*
* Precondition:
* 1. t has at-most one child
* 2. Stack ancestors has path from root to parent of t
* @param t the input element
*/
private void bypass(Entry<T> t) {
Entry<T> parent = ancestors.peek(); // parent of t
Entry<T> child = (t.left == null)? t.right: t.left; // Precondition 1
// when t is root of the tree
if (parent == null) root = child; // bypassing root
else {
// When the king(t) is dead, long live the king! ;)
if (parent.left == t) parent.left = child;
else parent.right = child; // t was rightChild of parent
}
}
/**
* Creates an array with the elements using in-order traversal of tree.
*/
public Comparable[] toArray() {
Comparable[] arr = new Comparable[size];
if (root == null) return null;
Stack<Entry<T>> ancestors = new Stack<Entry<T>>();
t = root;
int i=0;
while (t != null || ancestors.size() > 0) {
while (t != null) {
ancestors.push(t);
t = t.left;
}
t = ancestors.pop();
arr[i] = t.element;
i++;
t = t.right;
}
return arr;
}
// Start of Optional problem 2
/**
* Optional problem 2: Iterate elements in sorted order of keys Solve this
* problem without creating an array using in-order traversal (toArray()).
*/
public Iterator<T> iterator() {
return null;
}
// Optional problem 2. Find largest key that is no bigger than x. Return null if
// there is no such key.
public T floor(T x) {
return null;
}
// Optional problem 2. Find smallest key that is no smaller than x. Return null
// if there is no such key.
public T ceiling(T x) {
return null;
}
// Optional problem 2. Find predecessor of x. If x is not in the tree, return
// floor(x). Return null if there is no such key.
public T predecessor(T x) {
return null;
}
// Optional problem 2. Find successor of x. If x is not in the tree, return
// ceiling(x). Return null if there is no such key.
public T successor(T x) {
return null;
}
// End of Optional problem 2
public void printTree() {
System.out.print("[" + size + "]");
printTree(root);
System.out.println();
}
// Inorder traversal of tree
private void printTree(Entry<T> node) {
if (node != null) {
printTree(node.left);
System.out.print(" " + node.element);
printTree(node.right);
}
}
public static void main(String[] args) {
BinarySearchTree<Integer> t = new BinarySearchTree<>();
Scanner in = new Scanner(System.in);
while (in.hasNext()) {
int x = in.nextInt();
if (x > 0) {
System.out.print("Add " + x + " : ");
t.add(x);
t.printTree();
}
else if (x < 0) {
System.out.print("Remove " + x + " : ");
t.remove(-x);
t.printTree();
}
else {
Comparable[] arr = t.toArray();
System.out.print("Final: ");
for (int i = 0; i < t.size; i++) {
System.out.print(arr[i] + " ");
}
System.out.println();
return;
}
}
}
}