Last active
September 5, 2016 13:50
-
-
Save nishidy/d44efd9cc06796392f220f679a7a7c78 to your computer and use it in GitHub Desktop.
AVLTree with debugging the tree in Java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.io.*; | |
import java.util.*; | |
class AVLTree { | |
Queue<Node> queue; | |
List<Integer> valueList; | |
List<Label> labelList; | |
Node top; | |
public static void main (String[] args) throws java.io.IOException { | |
AVLTree tree = new AVLTree(); | |
if(args.length==0){ | |
tree.run(); | |
}else if(args.length==2){ | |
tree.test(Integer.parseInt(args[0]),Integer.parseInt(args[1])); | |
} | |
} | |
AVLTree (){ | |
queue = new LinkedList<Node>(); | |
valueList = new ArrayList<>(); | |
labelList = new ArrayList<>(); | |
top = new Node(0); | |
} | |
void test(int size, int disp) { | |
Random rnd = new Random(); | |
Node root = new Node(rnd.nextInt(size)); | |
top.left = root; | |
root.parent = top; | |
for(int i=0;i<size;i++){ | |
this.top.left.Push(new Node(rnd.nextInt(size))); | |
} | |
if(size<=32){ | |
Print(); | |
} | |
while(0<disp){ | |
long start = System.nanoTime(); | |
Node node = this.top.left.Search(rnd.nextInt(size)); | |
long end = System.nanoTime(); | |
if(node!=null){ | |
System.out.printf("Found node %d in %d ns.\n",node.value,end-start); | |
disp--; | |
} | |
} | |
} | |
void run() throws java.io.IOException { | |
BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); | |
String s; | |
System.out.printf("Please input the value for root node. : "); | |
s = in.readLine(); | |
Node root = new Node(Integer.parseInt(s)); | |
// XXX top is o ghost node only to rotate root node | |
// do not use right of top node | |
top.left = root; | |
root.parent = top; | |
System.out.println("('q' for quit, 'p' for print, 's' for search, 'd' for delete.)"); | |
Node node; | |
while(true){ | |
System.out.printf("Please input. : "); | |
s = in.readLine(); | |
if(s.equals("")){ | |
}else if(s.equals("q")){ | |
break; | |
}else if(s.equals("p")){ | |
Print(); | |
}else if(s.equals("s")){ | |
System.out.printf("Please input the value. : "); | |
s = in.readLine(); | |
node = this.top.left.Search(Integer.parseInt(s)); | |
System.out.println(node.value); | |
}else if(s.equals("d")){ | |
System.out.printf("Please input the value. : "); | |
s = in.readLine(); | |
this.top.left.Delete(Integer.parseInt(s)); | |
}else{ | |
this.top.left.Push(new Node(Integer.parseInt(s))); | |
} | |
} | |
} | |
int getHeight(Node node, int height){ | |
if(node==null){ | |
return height; | |
}else{ | |
return Math.max(getHeight(node.left,height+1),getHeight(node.right,height+1)); | |
} | |
} | |
void Print(){ | |
valueList.clear(); | |
labelList.clear(); | |
queue.clear(); | |
queue.add(top.left); | |
getTreeList(0); | |
int gap = 1; | |
int height = getHeight(top.left,0); | |
while(0<height--){ | |
gap = gap*2+3; | |
} | |
int level = 0; | |
int level_count = 0; | |
Integer value; | |
char label; | |
for(int idx=0;idx<valueList.size();idx++){ | |
value = valueList.get(idx); | |
if(value==null){ | |
if(valueList.get((idx-1)/2)==null){ | |
// if parent is also null | |
System.out.printf(" %s",getEmptySeq(gap," ")); | |
}else{ | |
System.out.printf(" []%s",getEmptySeq(gap," ")); | |
} | |
}else{ | |
label = labelList.get(idx).toString().charAt(0); | |
System.out.printf("%2d%s%s|%s",value,label,getEmptySeq(gap/2+1,"-"),getEmptySeq(gap/2-1," ")); | |
} | |
if(level_count == idx) { | |
gap = (gap-3)/2; | |
level ++; | |
level_count += Math.pow(2,level); | |
System.out.println(); | |
} | |
} | |
System.out.println(); | |
} | |
void getTreeList(int level){ | |
int qsize = queue.size(); | |
int i = 0; | |
Node node; | |
boolean notnull = false; | |
while(i<qsize){ | |
node = queue.peek(); queue.poll(); | |
if(node==null){ | |
valueList.add(null); | |
labelList.add(null); | |
queue.add(null); | |
queue.add(null); | |
}else{ | |
valueList.add(node.value); | |
labelList.add(node.label); | |
queue.add(node.left); | |
queue.add(node.right); | |
notnull = true; | |
} | |
i++; | |
} | |
if(notnull){ | |
if(queue.size()>0){ | |
getTreeList(level+1); | |
} | |
} | |
} | |
String getEmptySeq(int n, String sp){ | |
StringBuffer s = new StringBuffer(); | |
for(int i=0; i<n; i++){ | |
s.append(sp); | |
} | |
return s.toString(); | |
} | |
} | |
enum Label { | |
LEFT, | |
EQUAL, | |
RIGHT | |
} | |
class Node { | |
int value; | |
Node parent; | |
Node left; | |
Node right; | |
Label label; | |
Node(int value){ | |
this.value = value; | |
parent = null; | |
left = null; | |
right= null; | |
label = Label.EQUAL; | |
} | |
void Delete(int value){ | |
} | |
Node Search(int value){ | |
if(value == this.value){ | |
return this; | |
}else if(value < this.value){ | |
if(this.left==null){ | |
return null; | |
}else{ | |
return this.left.Search(value); | |
} | |
}else{ | |
if(this.right==null){ | |
return null; | |
}else{ | |
return this.right.Search(value); | |
} | |
} | |
} | |
Label Push(Node node){ | |
Label childLabel; | |
if(node.value < this.value){ | |
if(this.left == null){ | |
this.left = node; | |
node.parent = this; | |
childLabel = Label.LEFT; | |
}else{ | |
childLabel = this.left.Push(node); | |
} | |
if(childLabel == Label.EQUAL){ | |
return Label.EQUAL; | |
}else{ | |
switch(this.label){ | |
case LEFT : rotateLeft(); return Label.EQUAL; | |
case EQUAL: this.label = Label.LEFT; break; | |
case RIGHT: this.label = Label.EQUAL; break; | |
} | |
return this.label; | |
} | |
}else if(this.value < node.value){ | |
if(this.right == null){ | |
this.right = node; | |
node.parent = this; | |
childLabel = Label.RIGHT; | |
}else{ | |
childLabel = this.right.Push(node); | |
} | |
if(childLabel == Label.EQUAL){ | |
return Label.EQUAL; | |
}else{ | |
switch(this.label){ | |
case LEFT : this.label = Label.EQUAL; break; | |
case EQUAL: this.label = Label.RIGHT; break; | |
case RIGHT: rotateRight(); return Label.EQUAL; | |
} | |
return this.label; | |
} | |
} else { | |
return Label.EQUAL; | |
} | |
} | |
void rotateLeft(){ | |
//System.out.printf("Rotate left at %d!\n",this.value); | |
Node tmpLeft = this.left; | |
Node tmpParent = this.parent; | |
switch(tmpLeft.label){ | |
case LEFT: | |
this.left = tmpLeft.right; | |
if(tmpLeft.right!=null){ | |
tmpLeft.right.parent = this; | |
} | |
tmpLeft.right = this; | |
this.parent = tmpLeft; | |
if(tmpParent.left==this){ | |
tmpParent.left = tmpLeft; | |
}else{ | |
tmpParent.right = tmpLeft; | |
} | |
tmpLeft.parent = tmpParent;; | |
this.label = Label.EQUAL; | |
tmpLeft.label = Label.EQUAL; | |
break; | |
case RIGHT: | |
Node leftRight = tmpLeft.right; | |
this.left = leftRight.right; | |
if(this.left!=null){ | |
this.left.parent = this; | |
} | |
leftRight.right = this; | |
this.parent = leftRight; | |
tmpLeft.right = leftRight.left; | |
if(tmpLeft.right !=null){ | |
tmpLeft.right.parent = tmpLeft; | |
} | |
leftRight.left = tmpLeft; | |
tmpLeft.parent = leftRight; | |
if(tmpParent.left==this){ | |
tmpParent.left = leftRight; | |
}else{ | |
tmpParent.right = leftRight; | |
} | |
leftRight.parent = tmpParent; | |
if(leftRight.label == Label.RIGHT){ | |
this.label = Label.EQUAL; | |
tmpLeft.label = Label.LEFT; | |
}else if(leftRight.label == Label.LEFT){ | |
this.label = Label.RIGHT; | |
tmpLeft.label = Label.EQUAL; | |
}else{ | |
this.label = Label.EQUAL; | |
tmpLeft.label = Label.EQUAL; | |
} | |
leftRight.label = Label.EQUAL; | |
break; | |
} | |
} | |
void rotateRight(){ | |
//System.out.printf("Rotate right at %d!\n",this.value); | |
Node tmpRight = this.right; | |
Node tmpParent = this.parent; | |
switch(tmpRight.label){ | |
case RIGHT: | |
this.right = tmpRight.left; | |
if(tmpRight.left!=null){ | |
tmpRight.left.parent = this; | |
} | |
tmpRight.left = this; | |
this.parent = tmpRight; | |
if(tmpParent.right==this){ | |
tmpParent.right = tmpRight; | |
}else{ | |
tmpParent.left = tmpRight; | |
} | |
tmpRight.parent = tmpParent;; | |
this.label = Label.EQUAL; | |
tmpRight.label = Label.EQUAL; | |
break; | |
case LEFT: | |
Node rightLeft = tmpRight.left; | |
this.right = rightLeft.left; | |
if(this.right!=null){ | |
this.right.parent = this; | |
} | |
rightLeft.left = this; | |
this.parent = rightLeft; | |
tmpRight.left = rightLeft.right; | |
if(tmpRight.left !=null){ | |
tmpRight.left.parent = tmpRight; | |
} | |
rightLeft.right = tmpRight; | |
tmpRight.parent = rightLeft; | |
if(tmpParent.right==this){ | |
tmpParent.right = rightLeft; | |
}else{ | |
tmpParent.left = rightLeft; | |
} | |
rightLeft.parent = tmpParent; | |
if(rightLeft.label == Label.LEFT){ | |
this.label = Label.EQUAL; | |
tmpRight.label = Label.RIGHT; | |
}else if(rightLeft.label == Label.RIGHT){ | |
this.label = Label.LEFT; | |
tmpRight.label = Label.EQUAL; | |
}else{ | |
this.label = Label.EQUAL; | |
tmpRight.label = Label.EQUAL; | |
} | |
rightLeft.label = Label.EQUAL; | |
break; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment