Skip to content

Commit 6fe6448

Browse files
author
jkeys-e
committed
A wide range of basic data structures implemented in Java
0 parents  commit 6fe6448

23 files changed

+2783
-0
lines changed

AVL.java

Lines changed: 355 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,355 @@
1+
import java.util.Stack;
2+
3+
/**
4+
* Tree Node for AVL tree
5+
*
6+
* @author Huiping Cao
7+
*
8+
*/
9+
class AVLNode{
10+
private int data; //the element value for this node
11+
private AVL left; //the left child of this node
12+
private AVL right; //the right child of this node
13+
private int height; //height of the tree rooted at this node
14+
15+
public AVLNode() { data = 0; left = new AVL(); right = new AVL(); height = 0;}
16+
public AVLNode(int initData) { data = initData; left = new AVL(); right = new AVL(); height = 0;}
17+
18+
/**
19+
* Constructor with the initial element, initial left and right children
20+
* @param initData: the initial element
21+
* @param initLeft: left child
22+
* @param initRight: right child
23+
*/
24+
public AVLNode(int initData, AVL initLeft, AVL initRight){
25+
data = initData;
26+
left = initLeft;
27+
right = initRight;
28+
height = 1;
29+
}
30+
31+
32+
33+
public int getData() { return data; }
34+
public AVL getLeft() { return left; }
35+
public AVL getRight() { return right; }
36+
public int getHeight() { return height;}
37+
public void setData(int data) {this.data = data;}
38+
public void setLeft(AVL left) { this.left = left;}
39+
public void setRight(AVL right) { this.right = right;}
40+
41+
/**
42+
* Set the height of the tree rooted at this node
43+
*/
44+
public void setHeight()
45+
{
46+
this.height = 1+Math.max(getLeftHeight(), getRightHeight());
47+
}
48+
49+
50+
/**
51+
* Convert this BTNode to a string
52+
*/
53+
public String toString()
54+
{
55+
String str="";
56+
if(left==null) str +="(null)";
57+
else str +="("+left.getRoot().getData()+")";
58+
59+
str += data;
60+
61+
if(right==null) str +="(null)";
62+
else str +="("+right.getRoot().getData()+")";
63+
64+
return str;
65+
}
66+
67+
68+
/////////////////////////////////////////////////////////////////////////////
69+
/////////////////////////////////////////////////////////////////////////////
70+
//Rebalancing related methods
71+
72+
/**
73+
* Get the height of the left subtree
74+
*/
75+
public int getLeftHeight(){
76+
if(left==null||left.getRoot()==null) return 0;
77+
else return left.getRoot().getHeight();
78+
}
79+
80+
/**
81+
* Get the height of the right subtree
82+
* @return: the height of the right sub-tree
83+
*/
84+
public int getRightHeight(){
85+
if(right==null||right.getRoot()==null) return 0;
86+
else return right.getRoot().getHeight();
87+
}
88+
89+
}
90+
91+
92+
public class AVL {
93+
private AVLNode root; //instance variable to denote the root of the AVL tree
94+
95+
//Constructors for the AVL tree
96+
public AVL() {root = null;}
97+
public AVL(int e) {root = new AVLNode(e,new AVL(),new AVL());}
98+
99+
//Basic set and get methods
100+
public AVLNode getRoot() {return root;}
101+
public void setRoot(AVLNode _root) {this.root = _root;}
102+
public boolean isEmpty() {return (root==null);}
103+
104+
private AVL getLeftSubtree() { return root.getLeft(); }
105+
private AVL getRightSubtree() { return root.getRight(); }
106+
private void setHeight() {root.setHeight(); }
107+
108+
/**
109+
* Check whether the tree (rooted at this node) is right heavy or not
110+
* @return
111+
*/
112+
private boolean rightHeavy(){
113+
return (root.getLeftHeight() < root.getRightHeight());
114+
}
115+
116+
/**
117+
* Check whether the tree (rooted at this node) is left heavy or not
118+
* @param node
119+
* @return
120+
*/
121+
private boolean leftHeavy(){
122+
return (root.getLeftHeight() > root.getRightHeight());
123+
}
124+
125+
/**
126+
* Check whether the tree (rooted at this node) is right too heavy or not
127+
* @return
128+
*/
129+
private boolean rightTooHeavy(){
130+
return ((root.getLeftHeight()+1)< root.getRightHeight());
131+
}
132+
133+
/**
134+
* Check whether the tree (rooted at this node) is left too heavy or not
135+
* @param node
136+
* @return
137+
*/
138+
private boolean leftTooHeavy(){
139+
return (root.getLeftHeight() > (root.getRightHeight()+1));
140+
}
141+
142+
143+
/**
144+
* Traversal the tree in-order and print it
145+
*/
146+
public void inOrderTraversal(){
147+
inOrderTraversal(0);
148+
}
149+
150+
/**
151+
* Private function to print the tree with in-order traversal
152+
* @param indentation: the number of space before the data, to make the printing more beautiful
153+
*/
154+
private void inOrderTraversal(int indentation){
155+
if(root!=null){
156+
if(root.getRight()!=null)root.getRight().inOrderTraversal(indentation+1);
157+
for(int i=0;i<indentation*2;i++)
158+
System.out.print(" ");
159+
System.out.println(root.getData());
160+
if(root.getLeft()!=null)root.getLeft().inOrderTraversal(indentation+1);
161+
}
162+
}
163+
164+
public String inOrderStr()
165+
{
166+
if(root!=null)
167+
return (root.getLeft().inOrderStr() + " " + root.getData() + " " + root.getRight().inOrderStr());
168+
else
169+
return "";
170+
}
171+
172+
/**
173+
* Print the tree using pre-order traversal strategy recursively.
174+
*/
175+
public void preOrderPrtRecursive(){
176+
if(root==null) return;
177+
178+
System.out.print(root.getData()+" ");
179+
this.getLeftSubtree().preOrderPrtRecursive();
180+
this.getRightSubtree().preOrderPrtRecursive();
181+
}
182+
183+
private void rotateLeft() {
184+
AVL treeB = new AVL();
185+
treeB.root = getRightSubtree().root;
186+
187+
AVL T1 = getRightSubtree().getLeftSubtree();
188+
189+
getRightSubtree().root = T1.root;
190+
191+
treeB.getLeftSubtree().root = this.root;
192+
193+
this.root = treeB.root;
194+
195+
getLeftSubtree().setHeight();
196+
treeB.setHeight();
197+
treeB.getLeftSubtree().setHeight();
198+
this.setHeight();
199+
}
200+
201+
private void rotateRight() {
202+
AVL b = new AVL();
203+
b.root = getLeftSubtree().root;
204+
getLeftSubtree().root = getLeftSubtree().getRightSubtree().root;
205+
206+
b.getRightSubtree().root = this.root;
207+
208+
this.root = b.root;
209+
210+
getRightSubtree().setHeight();
211+
b.setHeight();
212+
b.getRightSubtree().setHeight();
213+
this.setHeight();
214+
}
215+
216+
private void doubleRotateRight() {
217+
getRightSubtree().rotateRight();
218+
this.rotateLeft();
219+
}
220+
221+
private void doubleRotateLeft() {
222+
getLeftSubtree().rotateLeft();
223+
this.rotateRight();
224+
}
225+
226+
227+
public void insert(int e) {
228+
if (root == null) {
229+
root = new AVLNode(e);
230+
root.setHeight();
231+
//this.rebalance();
232+
return;
233+
}
234+
if (e <= root.getData()) {
235+
//rebalance();
236+
getLeftSubtree().insert(e);
237+
setHeight();
238+
rebalance();
239+
}
240+
else {
241+
//rebalance();
242+
getRightSubtree().insert(e);
243+
setHeight();
244+
rebalance();
245+
}
246+
247+
}
248+
249+
private void rebalance() {
250+
if(root == null)
251+
return;
252+
253+
//System.out.println("in rebalance, this.data: " + this.root.getData() + "\ngetLeftHeight: " + root.getLeftHeight() + " and getRightHeight: " + root.getRightHeight());
254+
255+
if(leftTooHeavy()) {
256+
System.out.println("in rebalance, leftTooHeavy()");
257+
if(getLeftSubtree().rightHeavy())
258+
getLeftSubtree().rotateLeft();
259+
260+
rotateRight();
261+
262+
} else if(rightTooHeavy()) {
263+
System.out.println("in rebalance, rightTooHeavy()");
264+
if(getRightSubtree().leftHeavy())
265+
getRightSubtree().rotateRight();
266+
267+
rotateLeft();
268+
}
269+
270+
//getLeftSubtree().rebalance();
271+
//getRightSubtree().rebalance();
272+
273+
}
274+
275+
private void removeCurrentNode() {
276+
AVL left = getLeftSubtree();
277+
AVL right = getRightSubtree();
278+
279+
if(left.root == null && right.root == null)
280+
this.root = null;
281+
else if (left.root == null && right.root != null)
282+
this.root = right.root;
283+
else if (left.root != null && right.root == null)
284+
this.root = left.root;
285+
else {
286+
AVL rover = left;
287+
288+
while(rover.getRightSubtree().root != null) {
289+
rover = rover.getRightSubtree();
290+
}
291+
292+
this.root = rover.root;
293+
this.root.setRight(right);
294+
this.setHeight();
295+
this.rebalance();
296+
}
297+
}
298+
299+
public boolean remove(int e) {
300+
if(root == null) {
301+
return false;
302+
}
303+
304+
if(e == root.getData()) {
305+
this.removeCurrentNode();
306+
return true;
307+
} else if (e < root.getData()) {
308+
boolean result = getLeftSubtree().remove(e);
309+
setHeight();
310+
rebalance();
311+
return result;
312+
} else {
313+
boolean result = getRightSubtree().remove(e);
314+
setHeight();
315+
rebalance();
316+
return result;
317+
}
318+
}
319+
320+
public int countOccurrences(int e) {
321+
if(root == null) return 0;
322+
323+
if(root.getData() == e) return 1 + getLeftSubtree().countOccurrences(e) + getRightSubtree().countOccurrences(e);
324+
else return 0 + getLeftSubtree().countOccurrences(e) + getRightSubtree().countOccurrences(e);
325+
}
326+
327+
public void preOrderPrtNonRecursive() {
328+
if(root == null)
329+
return;
330+
331+
/*
332+
AVL roverPrev = this;
333+
AVL rover = roverPrev.getLeftSubtree();*/
334+
335+
Stack<AVL> s = new Stack<>();
336+
337+
s.push(this);
338+
339+
while(!s.empty()) {
340+
AVL curr = s.pop();
341+
342+
System.out.print(curr.getRoot().getData() + " ");
343+
//System.out.println("\ncurr.getRoot().getRightSub(): " + curr.getRoot().getRight());
344+
//System.out.println("\ncurr.getRoot().getLeftSub(): " + curr.getRoot().getLeft());
345+
346+
if(curr.getRightSubtree().getRoot() != null)
347+
s.push(curr.getRightSubtree());
348+
349+
if(curr.getLeftSubtree().getRoot() != null)
350+
s.push(curr.getLeftSubtree());
351+
352+
353+
}
354+
}
355+
}

0 commit comments

Comments
 (0)