I'm a little bit confused as to understanding how recursion works.
Basically I have to replace recursive methods with non recursive methods.
For example, this is the recursive method:
public Key min() {
if (isEmpty()) {
return null;
}
return min(root).key;
}
private Node min(Node x) {
if (x.left == null) {
return x;
} else {
return min(x.left);
}
}
public Key max() {
if (isEmpty()) {
return null;
}
return max(root).key;
}
private Node max(Node x) {
if (x.right == null) {
return x;
} else {
return max(x.right);
}
}
public Key floor(Key key) {
Node x = floor(root, key);
if (x == null) {
return null;
} else {
return x.key;
}
}
private Node floor(Node x, Key key) {
if (x == null) {
return null;
}
int cmp = key.compareTo(x.key);
if (cmp == 0) {
return x;
}
if (cmp < 0) {
return floor(x.left, key);
}
Node t = floor(x.right, key);
if (t != null) {
return t;
} else {
return x;
}
}
public Key ceiling(Key key) {
Node x = ceiling(root, key);
if (x == null) {
return null;
} else {
return x.key;
}
}
private Node ceiling(Node x, Key key) {
if (x == null) {
return null;
}
int cmp = key.compareTo(x.key);
if (cmp == 0) {
return x;
}
if (cmp < 0) {
Node t = ceiling(x.left, key);
if (t != null) {
return t;
} else {
return x;
}
}
return ceiling(x.right, key);
}
And this is my attempt of doing it non-recursively:
public Key min() {
if (isEmpty()) {
return null;
}
return min(root).key;
}
private Node min(Node x) {
while (x.left !=null){
x = x.left;
}
return x;
}
public Key max() {
if (isEmpty()) {
return null;
}
return max(root).key;
}
private Node max(Node x) {
while (x.right!=null){
x = x.right;
}
return x;
}
public Key floor(Key key) {
Node x = floor(root, key);
if (x == null) {
return null;
} else {
return x.key;
}
}
private Node floor(Node x, Key key) {
if (x == null) {
return null;
}
int cmp = key.compareTo(x.key);
if (cmp == 0) {
return x;
}
if (cmp < 0) {
while (x.left != null){
x = x.left;
if (x ==null){
return null;
}
}
}
Node t = x.right;
while (x.right != null){
x = x.right;
if (x == null){
return null;
}
}
if (t != null){
return t;
}
else{
return x;
}
}
I'm just asking if I have the right idea.
Yes, you have the right idea.
private Node min(Node x) {
if (x.left == null) {
return x;
} else {
return min(x.left);
}
}
This is good non-recursive solution of the function above.
private Node min(Node x) {
while (x.left !=null){
x = x.left;
}
return x;
}
You should take a look at http://en.wikipedia.org/wiki/Dynamic_programming, particularly Memoization.
Edit: Also take a look at similar thread: Way to go from recursion to iteration
Related
when I insert nodes into the binary tree and go test it out in the main by printing it in order the output is always wrong I have tried other solutions but it just keeps getting into bigger problems and in the output, it will be displayed in the wrong order I check the display its perfect but the problem is with the insert method (insert method insert non repeated keys).
class BSTNode<T> {
public int key;
public T data;
public BSTNode<T> left, right;
public BSTNode(int k, T val) {
key = k;
data = val;
left = right = null;
}
public BSTNode(int k, T val, BSTNode<T> l, BSTNode<T> r) {
key = k;
data = val;
left = l;
right = r;
}
}
public class BST<T> {
BSTNode<T> root, current;
public BST() {
root = current = null;
}
public boolean empty() {
return root == null;
}
public boolean full() {
return false;
}
public T retrieve() {
return current.data;
}
public boolean findkey(int tkey) {
BSTNode<T> p = root, q = root;
if (empty())
return false;
int nb = 0;
while (p != null) {
q = p;
nb++;
if (p.key == tkey) {
current = p;
return true;
} else if (tkey < p.key)
p = p.left;
else
p = p.right;
}
current = q;
return false;
}
public boolean insert(int key, T val) {
BSTNode<T> p = current, q = current;
while (p != null) {
q = p;
if (p.key == key) {
return false;
} else if (key < p.key)
p = p.left;
else
p = p.right;
}
p = new BSTNode<T>(key, val);
if (empty()) {
root = current = p;
return true;
} else {
// current is pointing to parent of the new key
if (key < current.key)
current.left = p;
else
current.right = p;
current = p;
return true;
}
}
public void display() {
if (root == null)
System.out.println("BST IS EMPTY");
else
displayin(root);
System.out.println();
}
private void displayin(BSTNode<T> p) {
if (p != null) {
displayin(p.left);
System.out.print(p.key + " " + p.data + " , ");
displayin(p.right);
}
}
}
In your insert method, the first code part:
while (p != null) {
q = p;
if (p.key == key) {
current = p;
return true;
} else if (key < p.key)
p = p.left;
else
p = p.right;
}
simply returns true when the key you want to write to is found. It does however not insert val here at all. You could have detected this by calling the insert method on some tree and then printing that tree, comparing the outcome that you had expected with the actual outcome. In automated form, you could do this with JUnit tests.
I think I know want you want (now). I have changed the "display"-Method to toString, rewrote insert and implemented a form of bfs for toString.
import java.util.ArrayList;
class BSTNode<T> {
public int key;
public T data;
public BSTNode<T> left, right;
public BSTNode(int k, T val) {
key = k;
data = val;
left = right = null;
}
public BSTNode(int k, T val, BSTNode<T> l, BSTNode<T> r) {
key = k;
data = val;
left = l;
right = r;
}
#Override
public String toString() {
return "[" + key + ":" + data + "]";
}
}
public class BST<T> {
BSTNode<T> root, current;
public BST() {
root = current = null;
}
public boolean empty() {
return root == null;
}
public T retrieve() {
return current.data;
}
public boolean findkey(int tkey) {
BSTNode<T> current = root;
while (current != null) {
if (current.key == tkey)
return true;
if (tkey < current.key)
current = current.left;
else
current = current.right;
}
return false;
}
public boolean insert(int key, T val) {
BSTNode<T> node = new BSTNode<>(key, val);
if (root == null) {
root = node;
} else {
BSTNode<T> current = root;
while (current != null) {
if (key == current.key)
return false;
if (key < current.key) {
if (current.left == null) {
current.left = node;
return true;
}
current = current.left;
} else {
if (current.right == null) {
current.right = node;
return true;
}
current = current.right;
}
}
}
return false;
}
public String toString() {
if (root == null)
return "BST IS EMPTY";
ArrayList<BSTNode<T>> visited = new ArrayList<>();
ArrayList<BSTNode<T>> queue = new ArrayList<>();
queue.add(root);
while (!queue.isEmpty()) {
BSTNode<T> vertex = queue.remove(0);
if (vertex != null) {
queue.add(vertex.left);
queue.add(vertex.right);
}
visited.add(vertex);
}
return visited.toString();
}
}
So, I am trying to implement insertion for a red black tree, using sentinels as described in the "Introduction to Algorithms".
I've created a Generic class for a red black node, which has type parameter as its data attribute and the other attributes: parent(node type), leftchild(node type), rightchild(node type) and a color(enum type having red and black values).
Red-Back Node Class:-
public class RedBlackTreeNode<T extends Comparable<T>> {
enum color{
RED,
BLACK
}
private T data;
private color color;
private RedBlackTreeNode<T> leftChild;
private RedBlackTreeNode<T> rightChild;
private RedBlackTreeNode<T> parent;
public RedBlackTreeNode(T data) {
this.data = data;
leftChild = null;
rightChild = null;
parent = null;
color = null;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
public color getColor() {
return color;
}
public void setColor(color color) {
this.color = color;
}
public RedBlackTreeNode<T> getLeftChild() {
return leftChild;
}
public void setLeftChild(RedBlackTreeNode<T> leftChild) {
this.leftChild = leftChild;
}
public RedBlackTreeNode<T> getRightChild() {
return rightChild;
}
public void setRightChild(RedBlackTreeNode<T> rightChild) {
this.rightChild = rightChild;
}
public RedBlackTreeNode<T> getParent() {
return parent;
}
public void setParent(RedBlackTreeNode<T> parent) {
this.parent = parent;
}
}
Red Black Tree Class:
import redBlackTree.RedBlackTreeNode.color;
public class RedBlackTree<T extends Comparable<T>> {
private RedBlackTreeNode<T> sentinel
;
private RedBlackTreeNode<T> root;
public RedBlackTree() {
sentinel = new RedBlackTreeNode<>(null);
sentinel.setColor(color.BLACK);
root = null;
}
public void redBlackInsert(RedBlackTreeNode<T> z) {
RedBlackTreeNode<T> y, x;
int temp;
y = sentinel;
x = this.root;
//Getting NullPointerException in the below while loop condition
while ((x.getData()) != null) {
y = x;
temp = z.getData().compareTo(x.getData());
if (temp < 0) {
x = x.getLeftChild();
} else {
x = x.getRightChild();
System.out.println("Right child of X: " + x);
System.out.println("Sentinel: " + x);
}
}
z.setParent(y);
if (y.getData() != null) {
temp = z.getData().compareTo(y.getData());
if (temp < 0) {
y.setLeftChild(z);
} else {
y.setRightChild(z);
}
} else {
root = z;
}
z.setLeftChild(sentinel);
z.setRightChild(sentinel);
z.setColor(color.RED);
redBlackInsertFix(z);
System.out.println("First node inserted");
}
private void redBlackInsertFix(RedBlackTreeNode<T> z) {
while (z.getParent().getColor() == color.RED) {
if (z.getParent() == z.getParent().getParent().getLeftChild()) {
RedBlackTreeNode<T> y;
y = z.getParent().getParent().getRightChild();
if (y.getColor() == color.RED) {
z.getParent().setColor(color.BLACK);
y.setColor(color.BLACK);
z.getParent().getParent().setColor(color.RED);
z = z.getParent().getParent();
} else if (z == z.getParent().getRightChild()) {
z = z.getParent();
leftRotate(z);
}
z.getParent().setColor(color.BLACK);
z.getParent().getParent().setColor(color.RED);
rightRotate(z.getParent().getParent());
} else {
RedBlackTreeNode<T> y;
y = z.getParent().getParent().getLeftChild();
if (y.getColor() == color.RED) {
z.getParent().setColor(color.BLACK);
y.setColor(color.BLACK);
z.getParent().getParent().setColor(color.RED);
z = z.getParent().getParent();
} else if (z == z.getParent().getLeftChild()) {
z = z.getParent();
rightRotate(z);
}
z.getParent().setColor(color.BLACK);
z.getParent().getParent().setColor(color.RED);
leftRotate(z.getParent().getParent());
}
}
root.setColor(color.BLACK);
}
private void rightRotate(RedBlackTreeNode<T> y) {
RedBlackTreeNode<T> x;
x = y.getLeftChild();
y.setLeftChild(x.getRightChild());
if (x.getRightChild() != sentinel) {
x.getRightChild().setParent(y);
}
x.setParent(y.getParent());
if (y.getParent() == sentinel) {
root = x;
} else if (y == y.getParent().getLeftChild()) {
y.getParent().setLeftChild(x);
} else {
y.getParent().setRightChild(x);
}
x.setRightChild(y);
y.setParent(x);
}
private void leftRotate(RedBlackTreeNode<T> x) {
RedBlackTreeNode<T> y;
y = x.getRightChild();
x.setRightChild(y.getLeftChild());
if (y.getLeftChild() != sentinel) {
y.getLeftChild().setParent(x);
}
y.setParent(x.getParent());
if (x.getParent() == sentinel) {
root = y;
} else if (x == x.getParent().getLeftChild()) {
x.getParent().setLeftChild(y);
} else {
x.getParent().setRightChild(y);
}
y.setLeftChild(x);
x.setParent(y);
}
public void inOrderTraversal(RedBlackTreeNode<T> x) {
if (x.getData() != sentinel.getData()) {
inOrderTraversal(x.getLeftChild());
System.out.println(x.getData());
inOrderTraversal(x.getRightChild());
}
}
public RedBlackTreeNode<T> getRoot() {
return root;
}
}
And here is the class having the main method:
public class RedBlackTreeDriver {
public static void main(String[] args) {
RedBlackTreeNode<Integer> one = new RedBlackTreeNode<>(50);
RedBlackTreeNode<Integer> two = new RedBlackTreeNode<>(55);
RedBlackTreeNode<Integer> three = new RedBlackTreeNode<>(48);
RedBlackTree<Integer> rbt = new RedBlackTree<>();
//System.out.println(rbt.getRoot());
//NullPointerException
rbt.redBlackInsert(one);
System.out.println("ROOT: "+ rbt.getRoot());
rbt.redBlackInsert(two);
rbt.redBlackInsert(three);
System.out.println(rbt.getRoot());
rbt.inOrderTraversal(rbt.getRoot());
}
}
I am trying to add a sentinel node(having the data attribute set as "null") after inserting every node with value. So, after adding the first node, I should be able to go down the tree(looking for sentinel) and add the new node to the parent of the sentinel.
I'm getting a null pointer exception in the Red Black Tree class.
So far,I've tried almost everything I know.
Can someone guide me through this?
Ok, so after thinking a bit, I got to this point where I just made sure that for the first time, when we are inserting a node, it should not check for the while loop condition.
And here it is, the change in the Red Black Tree Class:
package redBlackTree;
import redBlackTree.RedBlackTreeNode.color;
public class RedBlackTree<T extends Comparable<T>> {
private RedBlackTreeNode<T> sentinel;
private RedBlackTreeNode<T> root;
public RedBlackTree() {
sentinel = new RedBlackTreeNode<>(null);
sentinel.setColor(color.BLACK);
root = null;
}
public void redBlackInsert(RedBlackTreeNode<T> z) {
RedBlackTreeNode<T> y, x;
int temp;
y = sentinel;
x = this.root;
System.out.println(x);
// Getting NullPointerException in the below while loop condition
if (x != null) {
while (x.getData() != null) {
y = x;
temp = z.getData().compareTo(x.getData());
if (temp < 0) {
x = x.getLeftChild();
} else {
x = x.getRightChild();
System.out.println("Right child of X: " + x);
System.out.println("Sentinel: " + sentinel);
}
}
}
z.setParent(y);
if (y.getData() != null) {
temp = z.getData().compareTo(y.getData());
if (temp < 0) {
y.setLeftChild(z);
} else {
y.setRightChild(z);
}
} else {
root = z;
}
z.setLeftChild(sentinel);
z.setRightChild(sentinel);
z.setColor(color.RED);
redBlackInsertFix(z);
System.out.println("First node inserted");
}
private void redBlackInsertFix(RedBlackTreeNode<T> z) {
while (z.getParent().getColor() == color.RED) {
if (z.getParent() == z.getParent().getParent().getLeftChild()) {
RedBlackTreeNode<T> y;
y = z.getParent().getParent().getRightChild();
if (y.getColor() == color.RED) {
z.getParent().setColor(color.BLACK);
y.setColor(color.BLACK);
z.getParent().getParent().setColor(color.RED);
z = z.getParent().getParent();
} else if (z == z.getParent().getRightChild()) {
z = z.getParent();
leftRotate(z);
}
z.getParent().setColor(color.BLACK);
z.getParent().getParent().setColor(color.RED);
rightRotate(z.getParent().getParent());
} else {
RedBlackTreeNode<T> y;
y = z.getParent().getParent().getLeftChild();
if (y.getColor() == color.RED) {
z.getParent().setColor(color.BLACK);
y.setColor(color.BLACK);
z.getParent().getParent().setColor(color.RED);
z = z.getParent().getParent();
} else if (z == z.getParent().getLeftChild()) {
z = z.getParent();
rightRotate(z);
}
z.getParent().setColor(color.BLACK);
z.getParent().getParent().setColor(color.RED);
leftRotate(z.getParent().getParent());
}
}
root.setColor(color.BLACK);
}
private void rightRotate(RedBlackTreeNode<T> y) {
RedBlackTreeNode<T> x;
x = y.getLeftChild();
y.setLeftChild(x.getRightChild());
if (x.getRightChild() != sentinel) {
x.getRightChild().setParent(y);
}
x.setParent(y.getParent());
if (y.getParent() == sentinel) {
root = x;
} else if (y == y.getParent().getLeftChild()) {
y.getParent().setLeftChild(x);
} else {
y.getParent().setRightChild(x);
}
x.setRightChild(y);
y.setParent(x);
}
private void leftRotate(RedBlackTreeNode<T> x) {
RedBlackTreeNode<T> y;
y = x.getRightChild();
x.setRightChild(y.getLeftChild());
if (y.getLeftChild() != sentinel) {
y.getLeftChild().setParent(x);
}
y.setParent(x.getParent());
if (x.getParent() == sentinel) {
root = y;
} else if (x == x.getParent().getLeftChild()) {
x.getParent().setLeftChild(y);
} else {
x.getParent().setRightChild(y);
}
y.setLeftChild(x);
x.setParent(y);
}
public void inOrderTraversal(RedBlackTreeNode<T> x) {
if (x.getData() != sentinel.getData()) {
inOrderTraversal(x.getLeftChild());
System.out.println(x.getData());
inOrderTraversal(x.getRightChild());
}
}
public RedBlackTreeNode<T> getRoot() {
return root;
}
}
I hope this was not a very naive question to ask.
I've created an AVLTree in java and the add method should be of O(log n)... However my add method seems to give me a graph of O(c^n) or an exponential graph instead of a logarithmic graph. Here is the graph of running time vs input size:
Can anyone help figure out as to why this happens?
Here is the code for my AVLTree:
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Iterator;
import cw1.rs10.lib.IAVLTree;
public class AVLTree<K, V> implements IAVLTree<K, V>
{
public class Node {
private K key;
private ArrayList<V> values;
private Node left, right;
private int height;
public Node(K key, V value) {
this.key = key;
this.values = new ArrayList<V>();
this.left = null;
this.right = null;
this.height = 0;
values.add(value);
}
public K getKey() {
return key;
}
public void setKey(K key) {
this.key = key;
}
public ArrayList<V> getValues() {
return values;
}
public void addValue(V value) {
values.add(value);
}
public Node getLeft() {
return left;
}
public Node getRight() {
return right;
}
public void setLeft(Node left) {
this.left = left;
}
public void setRight(Node right) {
this.right = right;
}
public int getHeight() {
return height;
}
public void setHeight(int height) {
this.height = height;
}
}
private Node rootNode;
private Comparator<K> comparator;
//Unused
public AVLTree() {
}
public AVLTree(Comparator<K> comparator) {
this.rootNode = null;
this.comparator = comparator;
}
#Override
public V add(K k, V v) {
Node n = rootNode = add(k, v, rootNode);
if(n != null)
return v;
else
return null;
}
private Node add(K key, V value, Node node) {
if(node == null)
return new Node(key, value);
if(comparator.compare(key, node.getKey()) < 0) {
node.setLeft(add(key, value, node.getLeft()));
if(height(node.getLeft()) - height(node.getRight()) == 2) {
if(comparator.compare(key, node.getLeft().getKey()) < 0)
node = rotateLeft(node);
else
node = doubleRotateLeft(node);
}
} else if(comparator.compare(key, node.getKey()) > 0) {
node.setRight(add(key, value, node.getRight()));
if(height(node.getRight()) - height(node.getLeft()) == 2) {
if(comparator.compare(key, node.getRight().getKey()) > 0)
node = rotateRight(node);
else
node = doubleRotateRight(node);
}
} else {
//Handle duplicate
node.getValues().add(value);
}
node.setHeight( Math.max(height(node.getLeft()), height(node.getRight())) + 1 );
return node;
}
#Override
public V remove(K key, V value) throws Exception {
Node node = rootNode = remove(key, value, rootNode);
if(node != null)
return value;
else
return null;
}
private Node remove(K key, V value, Node node) {
//If node with key contains one or less values, remove the whole key
//Else remove value from node with key
if(node == null) return null;
else if(comparator.compare(key, node.getKey()) < 0) {
node.setLeft(remove(key, value, node.getLeft()));
if(height(node.getLeft()) - height(node.getRight()) == 2) {
if(comparator.compare(key, node.getLeft().key) < 0)
node = rotateLeft(node);
else
node = doubleRotateLeft(node);
}
} else if(comparator.compare(key, node.getKey()) > 0) {
node.setRight(remove(key, value, node.getRight()));
if(height(node.getRight()) - height(node.getLeft()) == 2) {
if(comparator.compare(key, node.getRight().key) < 0)
node = rotateRight(node);
else
node = doubleRotateRight(node);
}
} else {
if(node.getValues().size() > 1) {
node.getValues().remove(value);
return node;
} else {
if(node.getLeft() == null && node.getRight() == null)
return null;
if(node.getLeft() == null) return node.getRight();
if(node.getRight() == null) return node.getLeft();
Node smallestNode = smallestNode(node.getRight());
node = smallestNode;
node.setRight(remove(key, value, node.getRight()));
return node;
}
}
return node;
}
#Override
public Iterator<V> find(K key) {
Node n = search(key, rootNode);
if(n != null) {
ArrayList<V> values = n.getValues();
return values.iterator();
} else {
return new ArrayList<V>().iterator();
}
}
private Node search(K key, Node node) {
while(node != null) {
if(comparator.compare(key, node.getKey()) < 0)
node = node.getLeft();
else if(comparator.compare(key, node.getKey()) > 0)
node = node.getRight();
else
return node;
}
return null;
}
#Override
public Iterator<V> removeAll(K key) {
Node n = search(key, rootNode);
ArrayList<V> values = n.getValues();
try {
remove(n.getKey(), null);
} catch (Exception e) {
e.printStackTrace();
}
return values.iterator();
}
#Override
public Iterator<V> listAll() {
ArrayList<V> entries = new ArrayList<V>();
listAll(rootNode, entries);
return entries.iterator();
}
private void listAll(Node n, ArrayList<V> entries) {
if(n != null) {
listAll(n.getLeft(), entries);
entries.addAll(n.getValues());
listAll(n.getRight(), entries);
}
}
#Override
public int height() {
return height(rootNode);
}
//Custom Methods
/**
* A method to test if the tree is logically empty
*
* #return true if empty, false if not
*/
public boolean isEmpty() {
return rootNode == null;
}
/**
* Logically empties the tree by setting the rootNode to null
*/
public void empty() {
rootNode = null;
}
public void inOrderTraversal(Node node) {
if(node != null) {
inOrderTraversal(node.getLeft());
System.out.print(node.getKey() + ", ");
inOrderTraversal(node.getRight());
}
}
public int height(Node node) {
if(node == null) return -1;
else return node.height;
}
public Node getRootNode() {
return rootNode;
}
public Node smallestNode(Node node) {
if(node.getLeft() == null)
return node;
return smallestNode(node.getLeft());
}
private Node rotateLeft(Node node2) {
Node node1 = node2.getLeft();
node2.setLeft(node1.getRight());
node1.setRight(node2);
node2.setHeight(Math.max(height(node2.getLeft()), height(node2.getRight())) + 1);
node1.setHeight(Math.max(height(node1.getLeft()), node2.getHeight()) + 1);
return node1;
}
private Node rotateRight(Node node1) {
Node node2 = node1.getRight();
node1.setRight(node2.getLeft());
node2.setLeft(node1);
node1.setHeight(Math.max(height(node1.getLeft()), height(node1.getRight())) + 1);
node2.setHeight(Math.max(height(node2.getRight()), node1.getHeight()) + 1);
return node2;
}
private Node doubleRotateLeft(Node node3) {
node3.setLeft(rotateRight(node3.getLeft()));
return rotateLeft(node3);
}
private Node doubleRotateRight(Node node1) {
node1.setRight(rotateLeft(node1.getRight()));
return rotateRight(node1);
}
}
The interface for my AVLTree:
import java.util.Iterator;
public interface IAVLTree<K,V>
{
public V add(K k, V v);
public V remove(K k, V v);
public Iterator<V> removeAll(K k);
public Iterator<V> find(K k);
public Iterator<V> listAll();
public int height();
}
And finally, my testing code:
public class AVLTest
{
private static long startTime, endTime;
private static int amountOfCommands = 10000;
public static void main(String[] args) {
AVLTree<String, Integer> tree = new AVLTree<String, Integer>(String.CASE_INSENSITIVE_ORDER);
try {
startTime = System.currentTimeMillis();
for (int i = 1; i <= amountOfCommands; i++) {
String key = "K" + i;
tree.add(key, i);
}
endTime = System.currentTimeMillis();
} catch(Exception e) {
e.printStackTrace();
}
long runningTime = endTime - startTime;
System.out.println("Running Time: " + runningTime + "ms\nNo. of Commands: " + amountOfCommands);
}
}
You are measuring it wrong. Your test code measures the time to add all of the elements in the tree, instead of just one.
startTime = System.currentTimeMillis();
for (int i = 1; i <= amountOfCommands; i++) {
String key = "K" + i;
tree.add(key, i);
}
endTime = System.currentTimeMillis();
What you want to measure is the time it takes to add one node to the tree as a function of the number of nodes already in the tree.
for (int i = 1; i < amountOfCommands; i++) { // note the < instead of <=
String key = "K" + i;
tree.add(key, i);
}
String key = "K" + amountOfCommands;
startTime = System.currentTimeMillis();
tree.add(key, amountOfCommands);
endTime = System.currentTimeMillis();
Of course you can run your test more efficiently if you reuse the same tree for all measurements. I'll leave it to you.
My code is below but when I build the project, Netbeat gives me this warning:
Error: incomparable types: Object and int
if (p.info == x) {
Does anyone know how to fix this error? Thanks.
Here's error code:
public void insert(int x) {
if (root == null) {
root = new Node(x);
return;
}
Node f, p;
p = root;
f = null;
while (p != null) {
if (p.info == x) {
System.out.println(" The key " + x + " already exists, no insertion");
return;
}
f = p;
if (x < (int) p.info) {
p = p.left;
} else {
p = p.right;
}
}
if (x < (int) f.info) {
f.left = new Node(x);
} else {
f.right = new Node(x);
}
}
Here's all the code I have so far:
package ass6;
import java.util.ArrayList;
public class Ass6 {
public static void main(String[] args) {
BinarySearchTree bsTree = new BinarySearchTree();
String[] c = {"C6", "C2", "C7", "C1", "C5", "C9", "C4", "C8", "C3"};
bsTree.insertMany(c);
System.out.println("Calculate level of all nodes:");
bsTree.breadth_first_traverse3();
System.out.println("");
bsTree.calLevel(bsTree.root, 1);
bsTree.breadth_first_traverse();
System.out.println("");
System.out.println("\nCalculate the height of the tree:");
bsTree.calheight(bsTree.root);
bsTree.breadth_first_traverse1();
System.out.println("");
System.out.println("Calculate balance factor of all nodes:");
bsTree.breadth_first_traverse3();
System.out.println("");
bsTree.calbaFactor(bsTree.root);
bsTree.breadth_first_traverse2();
bsTree.AVL(bsTree.root);
System.out.println("");
System.out.println("Balance a binary search tree:");
bsTree.breadth_first_traverse3();
System.out.println("");
bsTree.balance();
bsTree.breadth_first_traverse3();
System.out.println("");
}
}
class BinarySearchTree {
Node root;
int height;
int i;
void clear() {
root = null;
}
public BinarySearchTree() {
root = null;
}
Node search(Node p, int x) {
if (p == null) {
return (null);
}
if ((int) p.info == x) {
return (p);
}
if (x < (int) p.info) {
return (search(p.left, x));
} else {
return (search(p.right, x));
}
}
public void insertMany(int a[]) {
for (int x : a) {
insert(x);
}
}
public void insertMany(String a[]) {
for (String x : a) {
insert(x);
}
}
public void insert(String x) {
if (root == null) {
root = new Node(x);
return;
}
Node f, p;
p = root;
f = null;
while (p != null) {
if (p.info == x) {
System.out.println(" The key " + x + " already exists, no insertion");
return;
}
f = p;
if (x.compareTo(p.info.toString()) < 0) {
p = p.left;
} else {
p = p.right;
}
}
if (x.compareTo(f.info.toString()) < 0) {
f.left = new Node(x);
} else {
f.right = new Node(x);
}
}
public void insert(int x) {
if (root == null) {
root = new Node(x);
return;
}
Node f, p;
p = root;
f = null;
while (p != null) {
if (p.info == x) {
System.out.println(" The key " + x + " already exists, no insertion");
return;
}
f = p;
if (x < (int) p.info) {
p = p.left;
} else {
p = p.right;
}
}
if (x < (int) f.info) {
f.left = new Node(x);
} else {
f.right = new Node(x);
}
}
public void visitLevel(Node x) {
System.out.print("(" + x.info + "," + x.level + "), ");
}
public void visit(Node x) {
System.out.print(x.info + ", ");
}
public void visitheight(Node x) {
System.out.print("(" + x.info + "," + x.height + "), ");
}
public void visitbafator(Node x) {
System.out.print("(" + x.info + "," + x.baFactor + "), ");
}
public void breadth_first_traverse() {
MyQueue queue = new MyQueue();
Node p = root;
if (p != null) {
queue.enqueue(p);
}
while (!queue.isEmpty()) {
Node q = (Node) queue.dequeue();
visitLevel(q);
if (q.left != null) {
queue.enqueue(q.left);
}
if (q.right != null) {
queue.enqueue(q.right);
}
}
}
public void breadth_first_traverse1() {
MyQueue queue = new MyQueue();
Node p = root;
if (p != null) {
queue.enqueue(p);
}
while (!queue.isEmpty()) {
Node q = (Node) queue.dequeue();
visitheight(q);
if (q.left != null) {
queue.enqueue(q.left);
}
if (q.right != null) {
queue.enqueue(q.right);
}
}
System.out.println("");
}
public void breadth_first_traverse2() {
MyQueue queue = new MyQueue();
Node p = root;
if (p != null) {
queue.enqueue(p);
}
while (!queue.isEmpty()) {
Node q = (Node) queue.dequeue();
visitbafator(q);
if (q.left != null) {
queue.enqueue(q.left);
}
if (q.right != null) {
queue.enqueue(q.right);
}
}
System.out.println("");
}
public void breadth_first_traverse3() {
MyQueue queue = new MyQueue();
Node p = root;
if (p != null) {
queue.enqueue(p);
}
while (!queue.isEmpty()) {
Node q = (Node) queue.dequeue();
visit(q);
if (q.left != null) {
queue.enqueue(q.left);
}
if (q.right != null) {
queue.enqueue(q.right);
}
}
}
public void inorder(Node x) {
if (x == null) {
return;
}
inorder(x.left);
visit(x);
inorder(x.right);
}
public void calLevel(Node n, int i) {
if (n.left == null && n.right == null) {
n.level = i;
} else {
n.level = i;
if (n.left != null) {
calLevel(n.left, i + 1);
}
if (n.right != null) {
calLevel(n.right, i + 1);
}
}
}
public int treeheight(Node p) {
if (p == null) {
return 0;
}
int left = treeheight(p.left);
int right = treeheight(p.right);
return 1 + Math.max(left, right);
}
public void calheight(Node n) {
if (n.left == null && n.right == null) {
n.height = 1;
} else {
n.height = treeheight(n);
if (n.left != null) {
calheight(n.left);
}
if (n.right != null) {
calheight(n.right);
}
}
}
public void calbaFactor(Node n) {
if (n.left == null && n.right == null) {
n.baFactor = 0;
} else {
n.baFactor = treeheight(n.right) - treeheight(n.left);
if (n.baFactor > 1 || n.baFactor < -1) {
i++;
}
if (n.left != null) {
calbaFactor(n.left);
}
if (n.right != null) {
calbaFactor(n.right);
}
}
}
public void AVL(Node n) {
if (i > 0) {
System.out.println("The tree is not an AVL tree .");
} else {
System.out.println("The tree is an AVL tree .");
}
}
void inOrder(ArrayList<String> t, Node p) {
if (p == null) {
return;
}
inOrder(t, p.left);
t.add((String) p.info);
inOrder(t, p.right);
}
void balance(ArrayList<String> t, int i, int j) {
if (i > j) {
return;
}
int k = (i + j) / 2;
String x = t.get(k);
insert(x);
balance(t, i, k - 1);
balance(t, k + 1, j);
}
void balance() {
ArrayList<String> t = new ArrayList<>();
inOrder(t, root);
int n = t.size();
clear();
balance(t, 0, n - 1);
}
}
class Node {
Object info;
int level = 1;
int height = 0;
int baFactor = 0;
Node left, right;
public Node(Object inf, Node le, Node ri) {
info = inf;
left = le;
right = ri;
}
public Node(Object inf) {
info = inf;
left = right = null;
}
}
class MyQueue {
ArrayList al = new ArrayList();
MyQueue() {
}
public void enqueue(Object x) {
al.add(x);
}
public Object dequeue() {
Object obj = al.get(0);
al.remove(0);
return obj;
}
public boolean isEmpty() {
if (al.size() <= 0) {
return true;
} else {
return false;
}
}
}
In java, you cannot compare primitive types (int, float, double, byte etc) with instance types (everything derived from Object and then instantiated).
Use p.info.equals(x)
here p.info is an Object,and x is an int so you cannot simply compare with ==. but
.equals will work, becase the value will be compared.
Object obj = Integer.valueOf(3);
int x=3;
if ( obj.equals(x) ) { // true
}
My source code:
import java.util.*;
public class Arvore {
public Arvore() {
root = null;
}
public void inserir(String x) {
root = insert(x, root);
}
public void remove(String x) {
root = remove(x, root);
}
private No remove(String x, No t) {
if (t == null) {
return t;
}
int comp = x.compareTo(t.str);
if (comp < 0) {
t.left = remove(x, t.left);
} else if (comp > 0) {
t.right = remove(x, t.right);
} else if (t.left != null && t.right != null) {
t.str = findMin(t.right).str;
t.right = remove(t.str, t.right);
} else {
t = (t.left != null) ? t.left : t.right;
}
return balance(t);
}
public String findMin() {
return findMin(root).str;
}
public String findMax() {
return findMax(root).str;
}
public boolean contains(String x) {
return contains(x, root);
}
public void makeEmpty() {
root = null;
}
public boolean isEmpty() {
return root == null;
}
private static final int maxBal = 1;
private No balance(No t) {
if (t == null) {
return t;
}
if (height(t.left) - height(t.right) > maxBal) {
if (height(t.left.left) >= height(t.left.right)) {
t = rotateWithLeftChild(t);
} else {
t = doubleWithLeftChild(t);
}
} else if (height(t.right) - height(t.left) > maxBal) {
if (height(t.right.right) >= height(t.right.left)) {
t = rotateWithRightChild(t);
} else {
t = doubleWithRightChild(t);
}
}
t.height = Math.max(height(t.left), height(t.right)) + 1;
return t;
}
public void checkBalance() {
checkBalance(root);
}
private int checkBalance(No t) {
if (t == null) {
return -1;
}
if (t != null) {
int hl = checkBalance(t.left);
int hr = checkBalance(t.right);
if (Math.abs(height(t.left) - height(t.right)) > 1
|| height(t.left) != hl || height(t.right) != hr) {
System.out.println("OOPS!!");
}
}
return height(t);
}
private No insert(String x, No t) {
if (t == null) {
return new No(x, null, null);
}
int comp = x.compareTo(t.str);
if (comp < 0) {
t.left = insert(x, t.left);
} else if (comp > 0) {
t.right = insert(x, t.right);
} else
;
t.occ+=1;
return balance(t);
}
private No findMin(No t) {
if (t == null) {
return t;
}
while (t.left != null) {
t = t.left;
}
return t;
}
private No findMax(No t) {
if (t == null) {
return t;
}
while (t.right != null) {
t = t.right;
}
return t;
}
private boolean contains(String x, No t) {
while (t != null) {
int comp = x.compareTo(t.str);
if (comp < 0) {
t = t.left;
} else if (comp > 0) {
t = t.right;
} else {
return true;
}
}
return false;
}
private void printTree(No t) {
if (t != null) {
printTree(t.left);
System.out.println(t.str + ": " + t.occ);
printTree(t.right);
}
}
private int height(No t) {
return t == null ? -1 : t.height;
}
private No rotateWithLeftChild(No k2) {
No k1 = k2.left;
k2.left = k1.right;
k1.right = k2;
k2.height = Math.max(height(k2.left), height(k2.right)) + 1;
k1.height = Math.max(height(k1.left), k2.height) + 1;
return k1;
}
private No rotateWithRightChild(No k1) {
No k2 = k1.right;
k1.right = k2.left;
k2.left = k1;
k1.height = Math.max(height(k1.left), height(k1.right)) + 1;
k2.height = Math.max(height(k2.right), k1.height) + 1;
return k2;
}
private No doubleWithLeftChild(No k3) {
k3.left = rotateWithRightChild(k3.left);
return rotateWithLeftChild(k3);
}
private No doubleWithRightChild(No k1) {
k1.right = rotateWithLeftChild(k1.right);
return rotateWithRightChild(k1);
}
private class No {
No(String tStr) {
this(tStr, null, null);
}
No(String tStr, No lt, No rt) {
str = tStr;
left = lt;
right = rt;
height = 0;
occ = 1;
}
String str;
No left;
No right;
int height;
int occ = 0;
}
private No root;
public static void main(String[] args) {
Arvore t = new Arvore();
System.out.println("AVL TREE TEST\n");
String msg;
String[] inputs;
Scanner sc = new Scanner(System.in);
ArrayList palavras = new ArrayList();
int i = 0;
while (true) {
msg = sc.nextLine();
if (msg.equals("")) {
break;
}
inputs = msg.split(" ");
i = 0;
while (i < inputs.length) {
palavras.add(inputs[i]);
}
}
i = 0;
while (i < palavras.size()) {
if (palavras.get(i).equals("REMOVE")) {
palavras.remove(palavras.get(i));
palavras.remove(palavras.get(i + 1));
i += 2;
} else {
t.insert(palavras.get(i));
}
i++;
}
t.printTree();
}
}
I can't figure out why i have an error when i call insert and printTree, on the main function.
And i have a warning by adding a string to my arraylist, when i do palavras.add(inputs[i]).
Your loop:
i = 0;
while (i < inputs.length) {
palavras.add(inputs[i]);
}
is not incrementing i, so you will eventually run out of space for the array as you try to insert an infinite number of references to inputs[0].
The warning is because you are using a raw ArrayList. Try declaring palavras as:
ArrayList<String> palavras = new ArrayList<>(); // new ArrayList<String>(); if pre Java 7
Your other loop:
i = 0;
while (i < palavras.size()) {
if (palavras.get(i).equals("REMOVE")) {
palavras.remove(palavras.get(i));
palavras.remove(palavras.get(i + 1));
i += 2;
} else {
t.insert(palavras.get(i));
}
i++;
}
will generate an IndexOutOfBoundsException if the first branch of the if is taken when i == palavras.size() - 1 when it tries to remove the second element. Even if you are guaranteed that "REMOVE" is always followed by another element, you need to either reverse the order of the removals:
palavras.remove(palavras.get(i + 1));
palavras.remove(palavras.get(i));
or remove the element at i twice:
palavras.remove(palavras.get(i));
palavras.remove(palavras.get(i));
(because when you call remove() it moves all succeeding elements down one position in the array).
You are calling t.printTree() but, there is no such method defined in class Arvore; the method you did define takes a tree as an argument. Same thing with insert(): the actual method that's available takes a String and a No as arguments.