Skip to content

Instantly share code, notes, and snippets.

@nishidy
Last active September 5, 2016 13:50
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nishidy/d44efd9cc06796392f220f679a7a7c78 to your computer and use it in GitHub Desktop.
Save nishidy/d44efd9cc06796392f220f679a7a7c78 to your computer and use it in GitHub Desktop.
AVLTree with debugging the tree in Java
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