Adds AVL tree rendering
parent
6f0227e188
commit
511950f24e
8
pom.xml
8
pom.xml
|
@ -20,5 +20,11 @@
|
|||
</plugins>
|
||||
</build>
|
||||
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>guru.nidi</groupId>
|
||||
<artifactId>graphviz-java</artifactId>
|
||||
<version>0.8.8</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
|
@ -1,13 +1,24 @@
|
|||
package net.abhinavsarkar.algorist;
|
||||
|
||||
import guru.nidi.graphviz.engine.Format;
|
||||
import guru.nidi.graphviz.engine.Graphviz;
|
||||
import guru.nidi.graphviz.model.MutableGraph;
|
||||
import guru.nidi.graphviz.model.MutableNode;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.Iterator;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.Optional;
|
||||
import java.util.Stack;
|
||||
import static guru.nidi.graphviz.model.Factory.*;
|
||||
|
||||
public class AVLTree<K extends Comparable<K>,V> implements Iterable<AVLTree.Entry<K,V>>
|
||||
{
|
||||
private Node<K,V> root = EmptyNode.instance();
|
||||
private Node<K,V> root;
|
||||
|
||||
public AVLTree(boolean rebalance) {
|
||||
root = EmptyNode.instance(rebalance);
|
||||
}
|
||||
|
||||
public void insert(K key, V val) {
|
||||
this.root = this.root.insert(key, val);
|
||||
|
@ -41,6 +52,13 @@ public class AVLTree<K extends Comparable<K>,V> implements Iterable<AVLTree.Entr
|
|||
return this.root.toStringBuilder(0).toString();
|
||||
}
|
||||
|
||||
public void renderToPNG(String fileName) throws IOException
|
||||
{
|
||||
MutableGraph graph = mutGraph("AVLTree").setDirected(true);
|
||||
this.root.addToGraph(graph);
|
||||
Graphviz.fromGraph(graph).height(1000).render(Format.PNG).toFile(new File(fileName));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<Entry<K, V>> iterator()
|
||||
{
|
||||
|
@ -59,6 +77,7 @@ public class AVLTree<K extends Comparable<K>,V> implements Iterable<AVLTree.Entr
|
|||
Optional<K> predecessor(K key);
|
||||
boolean isEmpty();
|
||||
StringBuilder toStringBuilder(int level);
|
||||
Optional<String> addToGraph(MutableGraph graph);
|
||||
boolean checkIfBST();
|
||||
boolean checkIfAVLT();
|
||||
|
||||
|
@ -73,13 +92,15 @@ public class AVLTree<K extends Comparable<K>,V> implements Iterable<AVLTree.Entr
|
|||
|
||||
private static class ValueNode<K extends Comparable<K>,V> implements Node<K, V>
|
||||
{
|
||||
private final boolean rebalance;
|
||||
private K key;
|
||||
private V val;
|
||||
private int height;
|
||||
private Node<K,V> left = EmptyNode.instance();
|
||||
private Node<K,V> right = EmptyNode.instance();
|
||||
private Node<K,V> left;
|
||||
private Node<K,V> right;
|
||||
|
||||
ValueNode(K key, V val) {
|
||||
ValueNode(K key, V val, boolean rebalance) {
|
||||
this.rebalance = rebalance;
|
||||
if (key == null) {
|
||||
throw new IllegalArgumentException("Key cannot be null");
|
||||
}
|
||||
|
@ -90,6 +111,8 @@ public class AVLTree<K extends Comparable<K>,V> implements Iterable<AVLTree.Entr
|
|||
this.key = key;
|
||||
this.val = val;
|
||||
this.height = 1;
|
||||
left = EmptyNode.instance(rebalance);
|
||||
right = EmptyNode.instance(rebalance);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -158,7 +181,7 @@ public class AVLTree<K extends Comparable<K>,V> implements Iterable<AVLTree.Entr
|
|||
{
|
||||
if (this.left.isEmpty())
|
||||
{
|
||||
return this.right.isEmpty() ? EmptyNode.instance() : this.right;
|
||||
return this.right.isEmpty() ? EmptyNode.instance(rebalance) : this.right;
|
||||
}
|
||||
else if (this.right.isEmpty())
|
||||
{
|
||||
|
@ -196,6 +219,10 @@ public class AVLTree<K extends Comparable<K>,V> implements Iterable<AVLTree.Entr
|
|||
private ValueNode<K, V> rebalance()
|
||||
{
|
||||
this.resetHeight();
|
||||
if (!rebalance) {
|
||||
return this;
|
||||
}
|
||||
|
||||
int balance = this.balance();
|
||||
if (balance > 1) {
|
||||
ValueNode<K, V> l = this.left.toValueNode();
|
||||
|
@ -320,15 +347,42 @@ public class AVLTree<K extends Comparable<K>,V> implements Iterable<AVLTree.Entr
|
|||
{
|
||||
return "{" + key + ':' + val + '}';
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<String> addToGraph(MutableGraph graph)
|
||||
{
|
||||
String name = getGraphNodeName();
|
||||
MutableNode node = mutNode(name);
|
||||
graph.add(node);
|
||||
left.addToGraph(graph).ifPresent(n -> graph.add(node.addLink(mutNode(n))));
|
||||
right.addToGraph(graph).ifPresent(n -> graph.add(node.addLink(mutNode(n))));
|
||||
return Optional.of(name);
|
||||
}
|
||||
|
||||
private String getGraphNodeName()
|
||||
{
|
||||
return this.height + ":" + this.key;
|
||||
}
|
||||
}
|
||||
|
||||
private static class EmptyNode<K extends Comparable<K>,V> implements Node<K,V>
|
||||
{
|
||||
@SuppressWarnings("rawtypes")
|
||||
private static final EmptyNode INSTANCE = new EmptyNode();
|
||||
private static final EmptyNode TRUE_INSTANCE = new EmptyNode(true);
|
||||
|
||||
public static <K extends Comparable<K>,V> EmptyNode<K,V> instance() {
|
||||
return INSTANCE;
|
||||
@SuppressWarnings("rawtypes")
|
||||
private static final EmptyNode FALSE_INSTANCE = new EmptyNode(false);
|
||||
|
||||
private final boolean rebalance;
|
||||
|
||||
private EmptyNode(boolean rebalance)
|
||||
{
|
||||
this.rebalance = rebalance;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <K extends Comparable<K>,V> EmptyNode<K,V> instance(boolean rebalance) {
|
||||
return rebalance ? TRUE_INSTANCE : FALSE_INSTANCE;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -340,7 +394,7 @@ public class AVLTree<K extends Comparable<K>,V> implements Iterable<AVLTree.Entr
|
|||
@Override
|
||||
public Node<K, V> insert(K key, V val)
|
||||
{
|
||||
return new ValueNode<>(key, val);
|
||||
return new ValueNode<>(key, val, rebalance);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -403,6 +457,11 @@ public class AVLTree<K extends Comparable<K>,V> implements Iterable<AVLTree.Entr
|
|||
{
|
||||
return "<NULL>";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<String> addToGraph(MutableGraph graph) {
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
||||
|
||||
private static StringBuilder gutter(int times) {
|
||||
|
@ -485,39 +544,40 @@ public class AVLTree<K extends Comparable<K>,V> implements Iterable<AVLTree.Entr
|
|||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args)
|
||||
public static void main(String[] args) throws IOException
|
||||
{
|
||||
AVLTree<String, String> bst = new AVLTree<>();
|
||||
bst.insert("q", "barista");
|
||||
bst.insert("y", "duck");
|
||||
bst.insert("k", "carpool");
|
||||
bst.insert("p", "duck");
|
||||
AVLTree<String, String> bst = new AVLTree<>(true);
|
||||
bst.insert("a", "barista");
|
||||
bst.insert("b", "duck");
|
||||
bst.insert("c", "carpool");
|
||||
bst.insert("e", "barista");
|
||||
bst.insert("d", "duck");
|
||||
bst.insert("f", "abhinav");
|
||||
bst.insert("j", "abhinav");
|
||||
bst.insert("t", "duck");
|
||||
bst.insert("s", "carpool");
|
||||
bst.insert("g", "carpool");
|
||||
bst.insert("e", "carpool");
|
||||
bst.insert("f", "barista");
|
||||
bst.insert("g", "duck");
|
||||
bst.insert("h", "abhinav");
|
||||
bst.insert("i", "abhinav");
|
||||
bst.insert("j", "duck");
|
||||
bst.insert("k", "carpool");
|
||||
bst.insert("l", "carpool");
|
||||
bst.insert("m", "abhinav");
|
||||
bst.insert("n", "duck");
|
||||
bst.insert("o", "abhinav");
|
||||
bst.insert("p", "abhinav");
|
||||
bst.insert("q", "carpool");
|
||||
bst.insert("r", "barista");
|
||||
bst.insert("s", "duck");
|
||||
bst.insert("t", "barista");
|
||||
bst.insert("u", "carpool");
|
||||
bst.insert("v", "abhinav");
|
||||
bst.insert("h", "duck");
|
||||
bst.insert("r", "abhinav");
|
||||
bst.insert("n", "abhinav");
|
||||
bst.insert("w", "carpool");
|
||||
bst.insert("u", "barista");
|
||||
bst.insert("w", "duck");
|
||||
bst.insert("x", "barista");
|
||||
bst.insert("y", "barista");
|
||||
bst.insert("z", "duck");
|
||||
bst.insert("b", "barista");
|
||||
bst.insert("o", "carpool");
|
||||
bst.insert("a", "abhinav");
|
||||
bst.insert("l", "duck");
|
||||
bst.insert("m", "barista");
|
||||
bst.insert("i", "barista");
|
||||
bst.insert("x", "duck");
|
||||
|
||||
System.out.println(bst);
|
||||
System.out.println(bst.root.checkIfBST());
|
||||
System.out.println(bst.root.checkIfAVLT());
|
||||
bst.renderToPNG("AVLTree.png");
|
||||
|
||||
System.out.println(bst.get("a"));
|
||||
System.out.println(bst.get("b"));
|
||||
|
|
Loading…
Reference in New Issue