AVL Tree: solving a StackOverflowError - java

Basically, I am implementing an AVL tree by reading a set of integers from a text file and then populate the tree by using the add() method. Also, the program is supposed to print in order the set of integers.
As I run the program, a StackOverflowError pops up. I think that this error is being triggered due to something malfunctioning in the add() method.
I would really appreaciate if someone helps me as I am new to this type of programming.
This is part of the Main Class:
public static void main(String[] args) throws FileNotFoundException
{
AVL s1 = new AVL();
Scanner file = new Scanner(new File("C:\\Users\\Dell\\Desktop\\integers.txt"));
while(file.hasNext())
{
// String str = file.next();
//int b = Integer.parseInt(str);
int b = file.nextInt();
s1.add(b);
}
v1.PrintInOrder(v1.root);
These are the add() and PrintInOrder() methods:
public boolean add(int key)
{
root = add(root, key);
return true;
}
private Node add(Node b1, int key)
{
if(b1 == null)
{
return new Node(key);
}
if(key < b1.element){
b1.left = add(b1.left, key);
}
else
{
b1.right = add(b1.right, key);
}
int Left_Height = getHeight(b1.left);
int Right_Height = getHeight(b1.right);
// a height imbalance requires that two subtrees differ by two
if(Math.abs(LeftHeight - RightHeight )== 2)
return Balance(n1);
else
{
n1.ResetHeight();
return b1;
}
}
public void PrintInOrder(Node b1){
if(b1 != null){
PrintInOrder(b1.left);
System.out.println(b1.element);
PrintInOrder(b1.right);
}
}
This is the Node class:
public class Node {
Node left;
Node right;
int element;
int height;
public Node(int keys){
this(keys, null, null);
}
public Node(int d, Node right1, Node left1){
element = d;
height = 0;
left = left1;
right = right1;
}
// This method recalculates the height if the right or left subtrees have been altered
public void ResetHeight(){
int LeftHeight = AVL.getHeight(left);
int RightHeight = AVL.getHeight(right);
height = 1 + Math.max(LeftHeight,RightHeight);
}

Since stack overflows commonly occur in recursion. Use your IDE and set a break at locations where you have done recusion, then debug. Step through it.

Related

Insert string in a Binary tree

I am trying to create a binary tree that takes strings but it uses "-" and "+" to go left or right if the sign is + insert left and if it's - then insert right. Here is a visual representation of what I am trying to do.
insert method should take the word and just a single sign for now and based of that insert right or left
Here is my code but I am getting nullpointer error. Apparently, I am not inserting into the right order
public class BinaryTree {
private static Node root = null;
private static Node sign = null;
public static void main(String[] args) {
// TODO Auto-generated method stub
BinaryTree bt = new BinaryTree();
bt.insert("to", "-");
bt.insert("the", "+");
bt.preorder();
}
private class Node {
String data;
String sign;
Node left;
Node right;
public Node(String w) {
data = w;
left = right = null;
}
// public Node(String w, String s) {
// data = w;
// sign = s;
// left = right = null;
//
// }
} // -----------------end of Node
private void insert(String val, String sign) {
root = insert(root, val, sign);
}
Node insert(Node r, String data, String passSign) {
if (r == null) {
return new Node(data);
}
if(r.sign.equals(passSign)) {
r.right = insert(r.right, data, passSign);
}
else if (r.sign.equals(passSign)){
r.left = insert(r.left, data, passSign);
}
return r;
}
public void preorder() {
preorder(root);
}
public void preorder(Node p) {
if (p != null) {
System.out.println(p.data);
preorder(p.left);
preorder(p.right);
}
}
}
The main problems are:
The BinaryTree nor the Node instances should have a sign member. The sign only plays a role during the insertion process, but has no meaning any more once a node is inserted
r.sign.equals(passSign) is therefore also not the correct condition to check. According to your description you should just check whether the sign is a "-" and go right, or else go left ("+"). There is no state of the node that influences this decision. So do passSign.charAt(0) == '-' instead.
When making the recursive call you should not pass the same sign again: it has already been processed. Instead, pass any signs that follow after the consumed one. You can use substring for that purpose.
The image shows a root node that has no value. Yet you are right in creating a tree instance with no node at all. So your insert method should deal with the case where the root is null, but the sign argument is not the empty string. In that case a root node should be created, but it should not hold the target data, as for that we should still go deeper in the tree. This principle could apply to any node, not only the root. So foresee the creation of such "place-holder" nodes and give them some default value (like "(null)").
Not a problem, but I find it more useful to print in inorder order, and indent the deeper nodes. This way you get an idea how the tree is structured.
Here is the corrected code:
public class BinaryTree {
private static Node root = null;
// No sign member needed;
public static void main(String[] args) {
BinaryTree bt = new BinaryTree();
bt.insert("to", "-");
bt.insert("the", "+");
bt.insert("buy", "-+");
bt.insert("imperial", "+-");
bt.insert("afflication", "++");
bt.inorder();
}
private class Node {
String data;
// No sign member needed;
Node left;
Node right;
public Node(String w) {
data = w;
left = right = null;
}
}
private void insert(String val, String sign) {
root = insert(root, val, sign);
}
Node insert(Node r, String data, String passSign) {
// Check whether there is a sign
if (passSign.length() == 0) {
return new Node(data);
}
// If needed, create a placeholder node so to be able to descend further
if (r == null) {
r = new Node("(null)");
}
if (passSign.charAt(0) == '-') {
// Extract the rest of the signs
r.right = insert(r.right, data, passSign.substring(1, passSign.length()));
}
else {
r.left = insert(r.left, data, passSign.substring(1, passSign.length()));
}
return r;
}
public void inorder() {
inorder(root, "");
}
// This method gives a bit more visual output
public void inorder(Node p, String indent) {
if (p != null) {
inorder(p.left, indent + " ");
System.out.println(indent + p.data);
inorder(p.right, indent + " ");
}
}
}

How to output the number of iterations needed to find a value in a BST? [duplicate]

This question already has answers here:
What causes "Can't find Symbol" and how to fix it?
(5 answers)
Closed 5 years ago.
I can't seem to make my program that implements a Binary Search Tree (using User input) and search for a value, to print out the number of iterations that were necessary to actually find this value.
I've created a method called 'getLastIterationCount()' that returns the number of iterations but when I want to print it out in my main method, I get an error on the line 'System.out.println(getLastIterationCount());'. I think that my method is not in the right place but I'm not sure whats missing. Any ideas how I could make this program work?
/* Class Node */
class Node
{
Node left, right;
int data;
/* Constructor */
public Node(int n)
{
left = null;
right = null;
data = n;
}
/* Function to get data from node */
public int getData()
{
return data;
}
/* Function to get left node */
public Node getLeft()
{
return left;
}
/* Function to get right node */
public Node getRight()
{
return right;
}
}
/* Class BST */
class BST
{
private Node root;
private int iterations;
/* Constructor */
public BST()
{
root = null;
}
/* Functions to insert data */
public void insert(int data)
{
root = insert(root, data);
}
/* Function to insert data recursively */
private Node insert(Node node, int data)
{
if (node == null)
node = new Node(data);
else
{
if (data <= node.data)
node.left = insert(node.left, data);
else
node.right = insert(node.right, data);
}
return node;
}
/* Functions to search for an element */
public boolean search(int val)
{
iterations=0;
iterations++;
return search(root, val);
}
/* Function to search for an element recursively */
private boolean search(Node r, int val)
{
iterations=0;
boolean found = false;
while ((r != null) && !found)
{
int rval = r.getData();
if (val < rval){
r = r.getLeft();
}
else if (val > rval){
r = r.getRight();
}
else
{
found = true;
break;
}
found = search(r, val);
}
return found;
}
public int getLastIterationCount(){
return iterations;
}
}
/* Class LinkedListBST */
public class LinkedListBST
{
public static void main(String[] args)
{
Scanner scan = new Scanner(System.in);
/* Creating object of BST */
BST bst = new BST();
System.out.println("Linked List Binary Search Tree Test\n");
char ch;
/* Accept input */
do
{
System.out.println("Enter integer element to insert");
bst.insert( scan.nextInt() );
System.out.println("\nDo you want to continue (Type y or n) \n");
ch = scan.next().charAt(0);
} while (ch == 'Y'|| ch == 'y');
System.out.println("\nEnter an element to be searched: ");
Scanner sc = new Scanner(System.in);
System.out.println("Search result : " + bst.search(sc.nextInt()));
System.out.println(getLastIterationCount()); //ISSUE IS HERE
sc.close();
}
}
You are accessing the method getLastIterationCount()without the object. Please call it using bst.getLastIterationCount()
You should call the method using the object bst that you have instantiated as below :
bst.getLastIterationCount();
I think your search code is already close to being correct. First, initialize the counter at the external entry point to search:
public boolean search(int val) {
iterations = 1;
return search(root, val);
}
Then, at each call to the private internal search method, increment the counter by one:
private boolean search(Node r, int val) {
++iterations; // increment counter by one for current iteration
boolean found = false;
while ((r != null) && !found) {
int rval = r.getData();
if (val < rval){
r = r.getLeft();
}
else if (val > rval) {
r = r.getRight();
}
else {
found = true;
break;
}
found = search(r, val);
}
return found;
}
I have assumed here that you want the number of recursive calls necessary to find the value. If instead you wanted the height at which an item was found, it is a different question.
Edit:
I noticed that you have a getter method for returning the count. It is an instance method and you should therefore call it as such:
bst.getLastIterationCount()

QuickSort on Doubly Linked List (Improper output)

I've been doing this problem for a while now.
I created one file named quickSort.java - chose the last element of a list as a pivot element. and tried to sort the numbers but somehow I'm not able to generate expected output. I tried so many probable options but I'm stuck! Please help to get the correct solution.
Here's my code of the file: quickSort.java
public void quickFun(Node node)
{
Node new_node = node;
/* To find the last element as pivot*/
while(new_node.next!=null)
{
new_node = new_node.next;
}
Node head = node;
Node tail = new_node;
quickSort(head, tail);
}
public void quickSort(Node head, Node tail)
{
Node q = partition(head,tail);
if(head!=q && head!=q.prev)
{
quickSort(head, q.prev);
}
if(tail!=q && tail!=q.next)
{
quickSort(q.next, tail);
}
}
public Node partition(Node low, Node high){
int p = high.data;
Node i = low.prev;
for(Node j = low; j!=high; j=j.next)
{
if(j.data <= p)
{
if(i==null)
{
i = low;
}
else
{
i = i.next;
}
swap(i.data, j.data);
}
}
if(i==null)
{
i = low;
}
else
{
i = i.next;
}
swap(i.data, high.data);
return i;
}
public void swap(int a , int b)
{
int t;
t = a;
a = b;
b = t;
}
Here quickFun receives head of the inserted LinkedList as an argument.
I'm basically stuck at quickSort(Node, Node) condition.
Please help me here to solve this problem.
You can't swap values like this:
public void swap(int a , int b)
{
int t;
t = a;
a = b;
b = t;
}
Java is pass-by-value, so a and b are local variables to swap; any changes you make to the values are lost when swap returns.
However, you could write:
public void swap(Node a , Node b)
{
int t;
t = a.data;
a.data = b.data;
b.data = t;
}
because this is updating fields on the two node instances, which are still passed by value, but the value is the reference to the instances.

Creating binary search tree

So far I have the algorithm figured out to add to my binary search tree, but I'm having a bit of difficulty translating it into code. The algorithm is as follows:
public void add(int v) {
Create a new node n to hold value v.
If tree is empty
Set root to n.
Else
Create temporary node reference m, initialized to root.
Loop looking for a gap (a null left or right pointer) that is on the
correct side of m for v
If v < m.value, look at the left pointer
If v >= m.value, look at the right pointer
If pointer on correct side is not null, set m to that child node and
continue looking
m = m.left or m = m.right
The search for insertion position stops when node m has a null pointer on
the correct side.
Insert the new node n at that position
m.left = n or m.right = n
}
So far I have:
public void add(int v) {
Node n = new Node(v);
if(root==null)
root = n;
else {
Node m = root;
while(...) {
if(...)
m = m.left;
else
m = m.right;
}
if(...)
m.left = m;
else
m.right = n;
}
}
I believe most of that is correct, but I don't know what needs to be done at places marked as "..."
first of all a binary search tree should not have any duplicate values, an important requirement you have not implemented in your code. I have implemented the binary search tree recently while learning datastructures in java. Here is the code i wrote:
public class OrderedBinaryTree
{
private int _elementsPresent = 0;
private Node _root = null;
private int [] _values = null;
private class Node
{
Node _left = null;
Node _right = null;
Node _parent = null;
int _value = 0;
public Node(int value,Node parent)
{
_value = value;
_parent = parent;
}
}
public void put(int value)
{
boolean valueInserted = false;
Node temp = _root;
while(!valueInserted)
{
if(_root == null)
{
_root = new Node(value,null);
break;
}
else if(value == temp._value)
{
System.out.println("the entered value is already present");
return;
}
else if(value<=temp._value)
{
if(temp._left == null)
{
temp._left = new Node(value,temp);
break;
}
else
{
temp = temp._left;
}
}
else
{
if(temp._right == null)
{
temp._right = new Node(value,temp);
break;
}
else
{
temp = temp._right;
}
}
}
_elementsPresent++;
}

Returning the nth term of an inorder traversal of a binary tree

I came up with this code but it requires a global variable Rank. Is there any way I can solve this problem without having to have a global variable?
int Rank = 0;
public int inOrderTraversal(TreeNode node, int n){
if(node==null)
return 0;
int x=inOrderTraversal(node.left,n);
if(x!=0)return x;
Rank++;
if(n==Rank) return node.data;
int y=inOrderTraversal(node.right,n);
int c= x==0 ? y:x;
return c;
}
I am just trying to return the nth term in an in-order traversal of a binary tree.
You can pass a TraversalState object down the recursion invocation chain, and store the number of nodes that you visited in a variable there:
class TraversalState {
public int rank = 0;
}
...
public int inOrderTraversal(TreeNode node, int n, TraversalState ts){
if(node==null)
return 0;
int x=inOrderTraversal(node.left,n, ts);
ts.rank++;
if(n==ts.rank) return node.data;
int y=inOrderTraversal(node.right,n, ts);
int c= x==0 ? y:x;
return c;
}
Now your implementation is thread-safe, because it does not use "global" objects. Invoke it as follows:
int r = inOrderTraversal(myNode, targetN, new TraversalState());
The recursive approach is easy to understand, but if your tree shape defies expectation, then you're at the mercy of maximum stack depth here, which is likely to be more limiting that heap memory consumed by an explicitly allocated stack structure. Hence, it's better to invest the time in building an iterative walker.
First, define the structure for the tree nodes themselves:
public final class TreeNode {
public final int data;
public final TreeNode left, right;
public TreeNode(int data, TreeNode left, TreeNode right) {
this.data = data;
this.left = left;
this.right = right;
}
public TreeNode(int data) {
this(data, null, null);
}
}
We're going to want a way to react to events signaled during a depth-first walk through the tree. Returning true from these methods indicates that the visitor wishes for the walk to continue; returning false requests that the walk stop as soon as possible.
public abstract class Visitor {
public boolean visitPre(TreeNode node) {
return true;
}
public boolean visitMid(TreeNode node) {
return true;
}
public boolean visitPost(TreeNode node) {
return true;
}
}
Now, define the iterative in-order walk algorithm:
final class InOrder {
private InOrder() {}
private static final class Breadcrumb {
public final TreeNode node;
public final boolean rightIsNext; // Not a great name.
public Breadcrumb(TreeNode node, boolean rightIsNext) {
this.node = node;
this.rightIsNext = rightIsNext;
}
public static Breadcrumb goingLeft(TreeNode departingPoint) {
return new Breadcrumb(departingPoint, true);
}
public static Breadcrumb goingRight(TreeNode departingPoint) {
return new Breadcrumb(departingPoint, false);
}
}
public static <T extends Visitor> T walk(TreeNode root, T visitor) {
if (null == root ||
null == visitor)
throw new NullPointerException();
final Deque<Breadcrumb> stack = new ArrayDeque<Breadcrumb>();
if (!visitor.visitPre(root))
return visitor;
for (;;) {
for (TreeNode left = root.left;
null != left;
root = left, left = root.left) {
if (!visitor.visitPre(left))
return visitor;
stack.push(Breadcrumb.goingLeft(root));
}
if (!visitor.visitMid(root))
return visitor;
final TreeNode right = root.right;
if (null != right) {
if (!visitor.visitPre(right))
return visitor;
stack.push(Breadcrumb.goingRight(root));
root = right;
} else {
if (!visitor.visitPost(root))
return visitor;
// Go back up the tree until we find a node with an unexplored right child.
for (;;) {
if (stack.isEmpty())
return visitor;
final Breadcrumb breadcrumb = stack.pop();
if (breadcrumb.rightIsNext) {
if (!visitor.visitMid(breadcrumb.node)) {
return visitor;
}
if (null != breadcrumb.node.right) {
if (!visitor.visitPre(breadcrumb.node.right))
return visitor;
stack.push(Breadcrumb.goingRight(breadcrumb.node));
root = breadcrumb.node.right;
break;
}
}
if (!visitor.visitPost(breadcrumb.node))
return visitor;
}
}
}
}
}
Exercise the walk() function on a sample tree:
(1)
|
+-+-+
| |
(2) (5)
|
+-+-+
| |
(3) -
|
+-+-+
| |
- (4)
That is, there are five nodes, where both leaves with data 4 and 5 are right children.
final TreeNode root = new TreeNode(1,
new TreeNode(2,
new TreeNode(3,
null,
new TreeNode(4)),
null),
new TreeNode(5));
walk(root,
new Visitor() {
private final PrintStream ps = System.out;
#Override
public boolean visitPre(TreeNode node) {
trace(node, "Pre");
return true;
}
#Override
public boolean visitMid(TreeNode node) {
trace(node, "Mid");
return true;
}
#Override
public boolean visitPost(TreeNode node) {
trace(node, "Post");
return true;
}
private TreeNode trace(TreeNode node, String phase) {
ps.print(phase);
ps.print('(');
ps.print(node.data);
ps.println(')');
return node;
}
});
This prints the following:
Pre(1)
Pre(2)
Pre(3)
Mid(3)
Pre(4)
Mid(4)
Post(4)
Post(3)
Mid(2)
Post(2)
Mid(1)
Pre(5)
Mid(5)
Post(5)
Post(1)
Now, you asked for a convenient way to find the nth node encountered during an in-order walk. We'll write a function called findNthInOrder(), where the parameter n designates zero as the first node encountered whose left subtree has already been explored, one designates the second, and so on:
private static TreeNode findNthInOrder(TreeNode root, final int n) {
if (n < 0)
throw new IllegalArgumentException();
return walk(root,
new Visitor() {
public TreeNode found = null;
private int remaining = n + 1;
#Override
public boolean visitMid(TreeNode node) {
if (0 == --remaining) {
found = node;
return false;
}
return true;
}
}).found;
}
Calling this function on our sample tree yields the expected result:
final TreeNode nth = findNthInOrder(root, 3);
System.out.println(null != nth ? nth.data : "(none)");
This prints "1" to the console, which matches the previous tracing walk over the sample tree: the fourth (that is, the zero-based index 3, per the argument above) emitted "Mid" trace is for the root node bearing the data value of one.
In summary, consider building enough to formalize the concepts in play, so that you can write these specific queries more confidently atop a sound foundation.
public int inOrderTraversal(TreeNode node, AtomicInteger n){
if(node == null) return 0;
if(n == 0) return node.data;
int leftVal = inOrderTraversal(node.left, n.decrementAndGet());
if(n == 0) return node.data;
int rightVal = inOrderTraversal(node.right,n.decrementAndGet());
return leftVal == 0 ? rightVal : leftVal;
}
Or to use MutuableInt from Apache commons lang instead of AtomicInteger.

Categories

Resources