-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathBinaryTree.java
More file actions
214 lines (159 loc) · 7.53 KB
/
BinaryTree.java
File metadata and controls
214 lines (159 loc) · 7.53 KB
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
public class BinaryTree<K, V> {
private Node<K, V> root;
BinaryTree(){
}
public Node<K, V> getRoot(){
return root;
}
// method called add that takes a K key and an V value as input and inserts the <key,
//value> pair into the next available position in your tree. In order to find the next available
//position: find a node whose left or right child is empty. If we find a node whose left child is
//empty, we make a new key as the left child of the node. Else if we find a node whose right
//child is empty, we make the new key as the right child. If both children are empty, insert on
//the left. If no nodes have been inserted yet, the first node inserted is the root. Traverse the
//tree (via in-order traversal) until we find a node whose either left or right child is empty.
//If key already appears in the tree, this method should not perform an addition, i.e. no
//repeated data items in the tree, and should return the value associated with the <key,
//value> pair already existing in the tree. If key was not already in tree, this method should
//return null
public V add (K key, V value){
if (lookup(key) != null) return lookup(key);
else if (root == null) {
root = new Node<>(key, value);
return null;
} else {
Node<K, V> parent = getFreeNode(root);
if(parent==null) return null;
Node<K, V> newnode = new Node<>(key, value);
if(parent.left==null){
parent.left = newnode;
}
else if(parent.right==null){
parent.right=newnode;
}
return null;
}
}
private Node<K, V> getFreeNode(Node<K, V> node){
if(node == null ){
return null;
}
else if(node.left== null || node.right==null) {
return node; //Returns the parentnode that has a free space
}
else {
return getFreeNode(node.left); // INORDER: LEFT - ROOT - RIGHT
//Recursive method that repeats the same algorithm on the left node, since we are in in-order traversal, the trees must grow to the left first.
}
}
//A method called remove that takes a K key as input and removes the associated <key,
//value> pair from the tree. The method should return the value if it successfully removed
//key from the tree, and it should return null if it did not remove key from the tree (i.e., if
//key was not in the tree).
//REMOVE NODE AND RECONNECT CHILDREN TO THE TREE
public V remove(K key){
Node<K, V> parentnode = removeHelper(root, key);//PARENT NODE
V value;
if(parentnode==null){
return null;
}
else if(parentnode.key.equals(key)){
value =parentnode.value;
//case you want to remove the root: IF there's a right child and IF there isn't
if(parentnode.right!=null) { //IF THERE'S A RIGHT CHILD
Node<K, V> newroot = parentnode.right; //right child will take the place of the root.
newroot.left = parentnode.left; //THE RIGHT CHILD WILL BECOME THE ROOT AND POINT TO ITS LEFT BROTHER (now child)
root = newroot;
root.right = null;
return value;
}
else{//Only left child / No child if root is the only node. (root.left== null -> root=null);
root= root.left;
}
return value;
}
if(parentnode.left.key.equals(key)){
Node<K,V> removenode = parentnode.left;
value = removenode.value;
//THREE CASES:
//FIRST: THE NODE HAS NO CHILDREN
if(removenode.left ==null && removenode.right==null) {
parentnode.left = null;
}
//SECOND: THE NODE HAS ONE CHILDREN (ON THE LEFT) - SO THE CHILD NODE JUST TAKES REMOVENODE'S PLACE
else if( removenode.left!=null && removenode.right==null){
parentnode.left= removenode.left;
}
//THIRD: THE NODE HAS TWO CHILDREN (LEFT AND RIGHT) SO THE RIGHT CHILDREN TAKES REMOVENODE'S PLACE AND STARTS TO POINT TO THE
// LEFT CHILDREN OF REMOVENODE
else{
parentnode.left= removenode.right; //PARENTNODE POINTS TO THE RIGHT CHILD OF REMOVENODE
removenode.right.left= removenode.left; //RIGHT CHILD OF REMOVENODE POINTS TO THE LEFT CHILD (SUBTREE) OF REMOVENODE
}
return value;
}
else if(parentnode.right.key.equals(key)){
Node<K,V> removenode = parentnode.right;
value = removenode.value;
//ONLY ONE CASE: THE RIGHT CHILD (TO BE REMOVED) HAS NO CHILDREN - SINCE INORDER TRAVERSAL, TREE WILL GROW ALWAYS TO THE LEFT
parentnode.right= null;
return value;
}
return null;
}
private Node<K, V> removeHelper(Node<K,V> node, K key) {
if (node == null) return null;
else if(node.key.equals(key)) return node; //case for root
else if(node.left==null && node.right==null) {
return null;
}
else if((node.left!=null && node.left.key.equals(key) || node.right!=null && node.right.key.equals(key))){
return node;
}
else {
Node<K, V> leftremove =removeHelper(node.left, key);
if(leftremove!=null) return leftremove; //if it isn't null, then it means that they found the node with the same key.
else{
return removeHelper(node.right, key); //if it wasn't on the left, then it must be on the right, or there isn't a node
//with the same key.
}
}
}
// A method called lookup that takes a K key as input and determines whether key appears
//in the tree. The method should return the associated value if the tree contains key and
//null otherwise
public V lookup(K key){
Node<K, V> node = lookupHelper(root, key);
if(node==null) return null;
else return node.value;
}
private Node<K, V> lookupHelper(Node<K,V> node,K key) {
if (node == null) return null;
else if(node.key.equals(key)){
return node;
}
else {
Node<K, V> leftlookup =lookupHelper(node.left, key);
if(leftlookup!=null) return leftlookup; //if it isn't null, then it means that they found the node with the same key.
else{
return lookupHelper(node.right, key); //if it wasn't on the left, then it must be on the right, or there isn't a node
//with the same key.
}
}
}
//A method called inOrderTraverse that, when called on the root, prints all <key,
//value> pairs in the tree via in-order traversal, with each pair appearing on a new line
//in the format (key, value). This method should have no input parameters and should
//not return anything.
public void inOrderTraverse(Node<K, V> node){
if(node == null) return;
else if(node.left==null && node.right == null){
System.out.println("(" + node.key + ", " + node.value + ")");
}
else{
inOrderTraverse(node.left);
System.out.println("(" + node.key + ", " + node.value + ")");
inOrderTraverse(node.right);
}
}
}