I have this code for BinaryTree creation and traversal
class Node
{
Integer data;
Node left;
Node right;
Node()
{
data = null;
left = null;
right = null;
}
}
class BinaryTree
{
Node head;
Scanner input = new Scanner(System.in);
BinaryTree()
{
head = null;
}
public void createNode(Node temp, Integer value)
{
Node newnode= new Node();
value = getData();
newnode.data = value;
temp = newnode;
if(head==null)
{
head = temp;
}
System.out.println("If left child exits for ("+value+") enter y else n");
if(input.next().charAt(0)=='y')
{
createNode(temp.left, value);
}
System.out.println("If right child exits for ("+value+") enter y else n");
if(input.next().charAt(0)=='y')
{
createNode(temp.right, value);
}
}
public Integer getData()
{
out.println("Enter the value to insert:");
return (Integer)input.nextInt();
}
public void print()
{
inorder(head);
}
public void inorder(Node node)
{
if(node!=null)
{
inorder(node.left);
System.out.println(node.data);
inorder(node.right);
}
else
return;
}
}
class BinaryTreeWorker
{
static BinaryTree treeObj = null;
static Scanner input = new Scanner(System.in);
public static void displaymenu()
{
int choice;
do{
out.print("\n Basic operations on a tree:");
out.print("\n 1. Create tree \n 2. Insert \n 3. Search value \n 4. print list\n Else. Exit \n Choice:");
choice = input.nextInt();
switch(choice)
{
case 1:
treeObj = createBTree();
break;
case 2:
treeObj.createNode(null, null);
break;
case 3:
//searchnode();
break;
case 4:
treeObj.print();
break;
default:
return;
}
}while(true);
}
public static BinaryTree createBTree()
{
return new BinaryTree();
}
public static void main(String[] args)
{
displaymenu();
}
}
It compiles and runs. But I think there is something wrong with the inorder traversal.
I created the below tree,
2
1 3
But it prints only 2.
I have tried solving the problem your way and I have pasted the solution below.. Though I haven't tested it thoroughly so it might fail in some edge condition.. But I have tested it for one case. Kindly let me know if it fails in some scenario. I would appreciate others help in making this answer better. I agree that this solution is not the most ideal way to code a Binary Tree but it wont hurt this way if some one is just practicing..
import java.util.Scanner;
class Node
{
Integer data;
Node left;
Node right;
Node()
{
data = null;
left = null;
right = null;
}
}
class BinaryTree
{
Node head;
Scanner input = new Scanner(System.in);
BinaryTree()
{
head = null;
}
public void createNode(Node temp,Node newnode)
{
if(head==null)
{
System.out.println("No value exist in tree, the value just entered is set to Root");
head = newnode;
return;
}
if(temp==null)
temp = head;
System.out.println("where you want to insert this value, l for left of ("+temp.data+") ,r for right of ("+temp.data+")");
char inputValue=input.next().charAt(0);
if(inputValue=='l'){
if(temp.left==null)
{
temp.left=newnode;
System.out.println("value got successfully added to left of ("+temp.data+")");
return;
}else {
System.out.println("value left to ("+temp.data+") is occupied 1by ("+temp.left.data+")");
createNode(temp.left,newnode);
}
}
else if(inputValue=='r')
{
if(temp.right==null)
{
temp.right=newnode;
System.out.println("value got successfully added to right of ("+temp.data+")");
return;
}else {
System.out.println("value right to ("+temp.data+") is occupied by ("+temp.right.data+")");
createNode(temp.right,newnode);
}
}else{
System.out.println("incorrect input plz try again , correctly");
return;
}
}
public Node generateTree(){
int [] a = new int[10];
int index = 0;
while(index<a.length){
a[index]=getData();
index++;
}
if(a.length==0 ){
return null;
}
Node newnode= new Node();
/*newnode.left=null;
newnode.right=null;*/
return generateTreeWithArray(newnode,a,0);
}
public Node generateTreeWithArray(Node head,int [] a,int index){
if(index >= a.length)
return null;
System.out.println("at index "+index+" value is "+a[index]);
if(head==null)
head= new Node();
head.data = a[index];
head.left=generateTreeWithArray(head.left,a,index*2+1);
head.right=generateTreeWithArray(head.right,a,index*2+2);
return head;
}
public Integer getData()
{
System.out.println("Enter the value to insert:");
return (Integer)input.nextInt();
}
public void print()
{
inorder(head);
}
public void inorder(Node node)
{
if(node!=null)
{
inorder(node.left);
System.out.println(node.data);
inorder(node.right);
}
else
return;
}
}
public class BinaryTreeWorker
{
static BinaryTree treeObj = null;
static Scanner input = new Scanner(System.in);
public static void displaymenu()
{
int choice;
do{
System.out.print("\n Basic operations on a tree:");
System.out.print("\n 1. Create tree \n 2. Insert \n 3. Search value \n 4. print list\n 5. generate a tree \n Else. Exit \n Choice:");
choice = input.nextInt();
switch(choice)
{
case 1:
treeObj = createBTree();
break;
case 2:
Node newnode= new Node();
newnode.data = getData();
newnode.left=null;
newnode.right=null;
treeObj.createNode(treeObj.head,newnode);
break;
case 3:
//searchnode();
break;
case 4:
System.out.println("inorder traversal of list gives follows");
treeObj.print();
break;
case 5:
Node tempHead = treeObj.generateTree();
System.out.println("inorder traversal of list with head = ("+tempHead.data+")gives follows");
treeObj.inorder(tempHead);
break;
default:
return;
}
}while(true);
}
public static Integer getData()
{
System.out.println("Enter the value to insert:");
return (Integer)input.nextInt();
}
public static BinaryTree createBTree()
{
return new BinaryTree();
}
public static void main(String[] args)
{
displaymenu();
}
}
[Update] : Updated the code to generate a binary tree using an array. This will involve less user interaction.
Best way to implement Binary Tree in Java with all the traverse types and test cases as below
package com.nitin.tree;
public class Tree
{
private Node parent;
private int data;
private int size = 0;
public Tree() {
parent = new Node(data);
}
public void add(int data) {
if (size == 0) {
parent.data = data;
size++;
} else {
add(parent, new Node(data));
}
}
private void add(Node root, Node newNode) {
if (root == null) {
return;
}
if (newNode.data < root.data) {
if (root.left == null) {
root.left = newNode;
size++;
} else {
add(root.left, newNode);
}
} else {
if (root.right == null) {
root.right = newNode;
size++;
} else {
add(root.right, newNode);
}
}
}
public int getLow() {
Node current = parent;
while (current.left != null) {
current = current.left;
}
return current.data;
}
public int getHigh() {
Node current = parent;
while (current.right != null) {
current = current.right;
}
return current.data;
}
private void in(Node node) {
if (node != null) {
in(node.left);
System.out.print(node.data + " ");
in(node.right);
}
}
private void pre(Node node) {
if (node != null) {
System.out.print(node.data + " ");
pre(node.left);
pre(node.right);
}
}
private void post(Node node) {
if (node != null) {
post(node.left);
post(node.right);
System.out.print(node.data + " ");
}
}
public void preorder() {
System.out.print("Preorder Traversal->");
pre(parent);
System.out.println();
}
public void postorder() {
System.out.print("Postorder Traversal->");
post(parent);
System.out.println();
}
public void inorder() {
System.out.print("Inorder Traversal->");
in(parent);
System.out.println();
}
private class Node {
Node left;
Node right;
int data;
public Node(int data) {
this.data = data;
}
}
public String toString() {
Node current = parent;
System.out.print("Traverse From Left ");
while (current.left != null && current.right != null) {
System.out.print(current.data + "->[" + current.left.data + " " + current.right.data + "] ");
current = current.left;
}
System.out.println();
System.out.print("Traverse From Right ");
current = parent;
while (current.left != null && current.right != null) {
System.out.print(current.data + "->[" + current.left.data + " " + current.right.data + "] ");
current = current.right;
}
return "";
}
public static void main(String af[]) {
Tree t = new Tree();
t.add(40);
t.add(25);
t.add(78);
t.add(10);
t.add(32);
t.add(50);
t.add(93);
t.add(3);
t.add(17);
t.add(30);
t.add(38);
System.out.println(t.getLow());
System.out.println(t.getHigh());
System.out.println("Size-" + t.size);
System.out.println(t);
t.inorder();
t.preorder();
t.postorder();
}
}
Your problem is in public void createNodes(Node temp, T data) function. You pass in a parameter the same name as the class variable temp. First of all I don't think you need the class variable by itself. Second of all assigning to temp in this method has only local effect - you loose the information in the temp parameter, but setting temp, will not infuence its value in the called method. I suggest you rewrite the method so that it returns the pointer to the newly created node and assign this pointer to the left and right of the local temp. That way the changes will propagate out.
another type of outputting the tree:
public void inorder()
{
inorder(root);
}
protected void visit(BSTNode<T> p)
{
System.out.println("Node: " + p.el + "Left Side:" + (p.left!=null?p.left.el:"null") +
"Right Side:" + (p.right!=null?p.right.el:"null"));
}
I've changed the BinaryTree Class as below. See the change on the the createNode method in particular.
The problem, as mentioned in the post before this, is that your reference doesn't persist when it is passed as an argument to the createNode method. That change is only local. You need to return an explicit Node reference in the method itself as you're creating the node.
public Node createNode()
{
Integer value = getData();
Node temp = new Node(value);
if(head==null)
{
head = temp;
}
System.out.println("Do you want to add left branch on node("+value+")? Enter y/n");
if(input.next().charAt(0)=='y')
{
temp.left=createNode();
}
System.out.println("Do you want to add right branch on node("+value+")? Enter y/n");
if(input.next().charAt(0)=='y')
{
temp.right=createNode();
}
return temp;
}
Here is the resulting output:
Basic operations on a tree:
1. Create tree
2. Insert
3. Search value
4. print list
Else. Exit
Choice:1
Basic operations on a tree:
1. Create tree
2. Insert
3. Search value
4. print list
Else. Exit
Choice:2
Enter the value to insert:
10
Do you want to add left branch on node(10)? Enter y/n
y
Enter the value to insert:
20
Do you want to add left branch on node(20)? Enter y/n
n
Do you want to add right branch on node(20)? Enter y/n
n
Do you want to add right branch on node(10)? Enter y/n
y
Enter the value to insert:
30
Do you want to add left branch on node(30)? Enter y/n
n
Do you want to add right branch on node(30)? Enter y/n
n
Basic operations on a tree:
1. Create tree
2. Insert
3. Search value
4. print list
Else. Exit
Choice:4
20
10
30
I hope this will be of some help to someone later (even if this is 3 years late..). I just started learning about Binary Trees today myself. I'm actually planning on using this as a base to doing more involved tasks!
I changed the createNode method so that it works:
public Node createNode(Node temp, Integer value)
{
Node newnode = new Node();
value = getData();
newnode.data = value;
temp = newnode;
if(head == null)
{
head = temp;
}
System.out.println("If left child exits for ("+value+") enter y else n");
if(input.next().charAt(0) == 'y')
{
newnode.left = createNode(newnode.left, value);
}
System.out.println("If right child exits for ("+value+") enter y else n");
if(input.next().charAt(0) == 'y')
{
newnode.right = createNode(newnode.right, value);
}
return newnode;
}
Related
(java)
I have class called Node, which has following fields:
value (integer)
connectedNodes (array of Node objects, always has same size = 2)
combination (object of Combination class)
Combination class has one field called messageContext, let's just say that it's a message which needs to be shown on the screen when something happens (described later).
Also, we have one Tree object, which has only one field: root (Node object)
Now, let's say that we have one String called combinationStr = "1121". Now, we use Tree's method called addCombination:
public void addCombination(Combination finalCombination, Node current, String combination, int counter) {
if(counter==combination.length()) {
return;
}
int value = combination.charAt(counter)-48;
if(current.connectedNodes[value-1]==null) {
current.connectedNodes[value-1] = new Node(value);
}
if(counter==combination.length()-1) {
current.combination = finalCombination;
return;
}
addCombination(finalCombination,current.connectedNodes[value-1],combination,counter+1);
}
finalCombination object is an object that is going to be assigned to the last Node's combination field, added to the Tree for one combinationStr. So, we use this function to create the Tree-like structure that has path: -1 (root) -> 1 -> 1 -> 2 -> 1
When we come to the last one, traversing the Tree, we should see message appear. This is the messageContext of finalCombination.
Okay so, now let's use while(true) loop that will let us input a number, which will be like a path-chooser. If we input 1, we will go to node 1 and have other options to choose.
While loop looks like this:
Scanner scanner = new Scanner(System.in);
Node currentNode = tree.root;
while(true) {
for(Node node: currentNode.connectedNodes) {
if(node!=null) {
System.out.print(node.value + " ");
continue;
}
System.out.print("nullnode ");
}
System.out.println("");
if(currentNode.combination!=null) {
System.out.println(currentNode.combination.messageContext);
}
if(currentNode.connectedNodes[0]==null && currentNode.connectedNodes[1]==null) {
currentNode = tree.root;
System.out.println("root");
}
int x = scanner.nextInt();
currentNode = tree.takeStep(currentNode,x);
}
So, what are we doing here is actually printing the value of current Node, then printing values of Node's we can go to. If Node doesn't exist, we print nullnode.
The takeStep() method looks like this:
public Node takeStep(Node current, int value) {
if(current.connectedNodes[value-1]!=null) {
return current.connectedNodes[value-1];
}
return this.root;
}
It just checks if there is a node we want to go to and returns that node, if it does. If it doesn't exist, it will return us to root.
But, what's the problem with this code ?
Well, look at the whole main class:
Tree tree = new Tree(new Node(-1));
String[] combination = {"1121","11","2212"};
for(String s: combination) {
Combination tempCombination = new Combination();
tempCombination.messageContext = s + " ova poruka";
tree.addCombination(tempCombination,tree.root,s,0);
tree.traverse(tree.root);
System.out.println("END");
}
Scanner scanner = new Scanner(System.in);
Node currentNode = tree.root;
while(true) {
System.out.println(currentNode.value);
for(Node node: currentNode.connectedNodes) {
if(node!=null) {
System.out.print(node.value + " ");
}
else {
System.out.print("nullnode ");
}
}
int x = scanner.nextInt();
if(currentNode.combination!=null) {
System.out.println(currentNode.combination.messageContext);
if(currentNode.connectedNodes[0]==null && currentNode.connectedNodes[1]==null) {
currentNode = tree.root;
break;
}
}
currentNode = tree.takeStep(currentNode,x);
}
When we enter number x, we will call takeStep and check if that node exists connected to current one. But the problem is: When we input 1, it prints everything normally, when we input 1 again, it prints everything normally, when we input 2, it prints everything normally... but when we input 1 again, it says there are 2 nullnodes, and for some reason it doesn't change to root. Can anyone help me please? Here are the full classes:
NODE:
public class Node {
int value;
Node[] connectedNodes = {null,null};
Combination combination;
public Node(int value) {
this.value = value;
this.combination = null;
}
}
TREE:
public class Tree {
Node root;
public Tree(Node root) {
this.root = root;
}
public void addCombination(Combination finalCombination, Node current, String combination, int counter) {
if(counter==combination.length()) {
return;
}
int value = combination.charAt(counter)-48;
if(current.connectedNodes[value-1]==null) {
current.connectedNodes[value-1] = new Node(value);
}
if(counter==combination.length()-1) {
current.combination = finalCombination;
return;
}
addCombination(finalCombination,current.connectedNodes[value-1],combination,counter+1);
}
public void traverse(Node current) {
System.out.print(current.value+ " ");
for(Node node: current.connectedNodes) {
if(node!=null) {
traverse(node);
}
}
}
public Node takeStep(Node current, int value) {
if(current.connectedNodes[value-1]!=null) {
return current.connectedNodes[value-1];
}
return this.root;
}}
COMBINATION:
public class Combination {
String messageContext;
}
Can you please help me ? I just want to reset to root when it hasn't anywhere to go else ? Thank you in advance!
I ran your code and found out that you are storing the message context in the parent node instead of the actual node which marks the end of the combination. So I changed this piece of code in addCombination.
public void addCombination(Combination finalCombination, Node current, String combination, int counter) {
if (counter == combination.length()) {
//Storing at the original node.
current.combination = finalCombination;
return;
}
int value = combination.charAt(counter) - 48;
if (current.connectedNodes[value - 1] == null) {
current.connectedNodes[value - 1] = new Node(value);
}
addCombination(finalCombination, current.connectedNodes[value - 1], combination, counter + 1);
}
And changed following in the main code.
while (true) {
System.out.println(currentNode.value);
//Moved it up now as the node it self has the message context.
if (currentNode.combination != null) {
System.out.println(currentNode.combination.messageContext);
if (currentNode.connectedNodes[0] == null && currentNode.connectedNodes[1] == null) {
currentNode = tree.root;
continue;
}
}
for (Node node : currentNode.connectedNodes) {
if (node != null) {
System.out.print(node.value + " ");
} else {
System.out.print("nullnode ");
}
}
int x = scanner.nextInt();
currentNode = tree.takeStep(currentNode, x);
}
Now try the code it is resetting to root as expected.
We are writing a project where we used linked lists to add and subtract numbers within a BST. However, we are able to add numbers but unable to delete them. Could someone look at our deletion function to see what's wrong?
// 2016 Spring Data Structure BST Sample Code at MIU (For the project #2)
// You may add/modify the classes but should maintain the basic structure of the classes.
import java.util.*;
import java.util.*;
class Node {
int data; // data
Node lc; //left child pointer
Node rc; //right child pointer
Node(int data){ // constructor
this.data=data;
lc=null;
rc=null;
}
}
class BST {
Node root;
BST(){
root=null;
}
void insert(int newData){ // This is not the full version
Node newNode=new Node(newData);
if(root==null) root=newNode; // root was null
else { // root was not null, so find the place to attach the new node
Node ptr=root; // Node pointer
while(true){
if(newNode.data==ptr.data) {
System.out.println("The node already exist.");
break;
}
else if(newNode.data<ptr.data) {
if(ptr.lc!=null) ptr=ptr.lc;
else {
ptr.lc=newNode;
System.out.println(newNode.data+" was successfully inserted.");
break;
}
}
else if(newNode.data>ptr.data) {
if(ptr.rc!=null) ptr=ptr.rc;
else {
ptr.rc=newNode;
System.out.println(newNode.data+" was successfully inserted.");
break;
}
}
}
}
}
Node delete(Node root,int key){ // delete the nodes
if (root == null) return null;
if (root.data > key) {
root.lc = delete(root.lc, key);
}
else if (root.data < key) {
root.rc = delete(root.rc, key);
}
return null;
}
boolean search(Node root,int key){ // if the search is successful return the Node or return null
if(root==null){
return false;
}
if(root.data== key) {
return true;
}
if(root.data!= key){
return false;
}
return true;
}
int number_nodes(Node n){ // the counting left child
if(n == null)
return 0;
if(n.lc ==null && n.rc==null)
return 1;
else
return 1+number_nodes(n.lc);
}
int rnumber_nodes(Node n){ // the counting right child
if(n == null)
return 0;
if(n.lc ==null && n.rc==null)
return 1;
else
return 1+number_nodes(n.rc);
}
void inorder(Node n){ // recursive inorder travelsal
if(n==null) return;
System.out.print("[");
inorder(n.lc);
System.out.print(n.data);
inorder(n.rc);
System.out.print("]");
}
void preorder(Node n){ // recursive preorder travelsal
if(n==null) return;
System.out.print("[");
System.out.print(n.data);
preorder(n.lc);
preorder(n.rc);
System.out.print("]");
}
void postorder(Node n){ // recursive postorder travelsal
if(n==null) return;
System.out.print("[");
postorder(n.lc);
postorder(n.rc);
System.out.print(n.data);
System.out.print("]");
}
}
public class BST_2015134 { // change the name into your IDs
public static void main(String[] args) {
BST bst=new BST();
Scanner sScan=new Scanner(System.in); // menu
Scanner iScan=new Scanner(System.in); // data
while(true){
System.out.print("\n(q)uit,(i)nsert,(d)elete,(s)earch,i(n)order,(p)reorder,p(o)storder,(h)ow many:");
String uChoice=sScan.next();
if(uChoice.equalsIgnoreCase("i")){
System.out.print("Enter a number to insert:");
int uData=iScan.nextInt();
bst.insert(uData);
}
else if(uChoice.equalsIgnoreCase("d")){ // deletion
System.out.print("enter the delete number");
Scanner s=new Scanner(System.in); // to use new scanner
int delete_num=s.nextInt(); //
bst.delete(bst.root,delete_num);
}
else if(uChoice.equalsIgnoreCase("s")){ // search
System.out.print("enter the search number");
Scanner s=new Scanner(System.in);
int search_num=s.nextInt();
if(bst.search(bst.root,search_num)){
while(true){
System.out.println(" your number is found"); // to tell you your # is found or not found
break;
}
}
else{
System.out.println(" your number is not found");
}
}
else if(uChoice.equalsIgnoreCase("n")){ // in order
bst.inorder(bst.root);
}
else if(uChoice.equalsIgnoreCase("p")){ // pre order
bst.preorder(bst.root);
}
else if(uChoice.equalsIgnoreCase("o")){ // post order
bst.postorder(bst.root);
}
else if(uChoice.equalsIgnoreCase("h")){ // how many
int x,y;
x=bst.number_nodes(bst.root);
y=bst.rnumber_nodes(bst.root);
int total=x+y;
System.out.print(total);
}
if(uChoice.equalsIgnoreCase("q")) break; // quit
}
}
}
Just a recap of what you are doing with this function:
If the key is expected to be contained by the left subtree, remove if from the left subtree with recursion. If the key is expected to be contained by the right subtree, remove if from the left subtree with recursion.
So far so good. However, you return null every time, so all the work you do is actually lost.
You also need to handle the case where the data of the node is equal to the given key. In that case you need to restructure the tree somehow.
The code below should do what you want as long as the node you want to delete is not the root of the tree (you should add a special case for that)
Node delete(Node root,int key){ // delete the nodes
if (root == null) return null;
if (root.data > key) {
root.lc = delete(root.lc, key);
}
else if (root.data < key) {
root.rc = delete(root.rc, key);
}else{
if(root.rc == null)
return root.lc;
if(root.lc == null)
return root.rc;
//if both the left and right child are effective, you need to restructure the tree
int minData = findMinimum(root.rc);
Node newNode = new Node(minData);
newNode.lc = root.lc;
newNode.rc = delete(root.rc, minData);
return newNode;
}
return root;
}
private int findMinimum(Node root){
if (root.lc == null)
return root.data;
else
return findMinimum(root.lc);
}
Note that removing a node from a BST is not trivial. Have a look at this link for more info.
Also note that this tree wil not be very efficient. A balanced tree would we a lot better.
I have implemented a code which adds elements in a tree and prints them in increasing order. However my aim is to learn iterators and want to replace the inOrder() function with an iterator function. How can I do this?
import java.util.InputMismatchException;
import java.util.Scanner;
import javax.xml.soap.Node;
class Tree
{
public final int mVal;
public Tree mLeft;
public Tree mRight;
public Node next;
public Tree(int val)
{
mVal = val;
}
public void add(int val)
{
if (val < mVal)
{
if (mLeft == null)
mLeft = new Tree(val);
else
mLeft.add(val);
}
else
{
if (val > mVal)
{
if (mRight == null)
mRight = new Tree(val);
else
mRight.add(val);
}
}
}
public String inOrder()
{
return ((mLeft == null) ? "" : mLeft.inOrder())
+ mVal + " "
+ ((mRight == null) ? "" : mRight.inOrder());
}
public static void main(String[] args)
{
Tree t = new Tree(8);
Scanner scanner = new Scanner(System.in);
boolean continueLoop = true; // determines if more input is needed
for (int i = 1; i < 9; ++i)
{
try // read two numbers and calculate quotient
{
System.out.print("Please enter a random integer : ");
int stackInt = scanner.nextInt();
t.add(Integer.valueOf(stackInt));
} // end try
catch (InputMismatchException inputMismatchException){
System.err.printf("\nException: %s\n", inputMismatchException);
scanner.nextLine(); //discard input so user can try again
System.out.println("You must enter integers. Please try again.\n");
} // end catch
}
System.out.println("Values in order = "+ t.inOrder());
}
}
look at this picture
First Step: if node has a left child, visit left child and do the first step with the child
Second Step: node has no left child (or we visited the left child already), add it to the inorder list
Third Step: first step with right child
i didnt test it
#Override
public String toString() {
return String.valueOf(mVal);
}
public String inOrder(Tree root) {
List<Tree> inOrder = new ArrayList<>();
inOrderRecursively(root, inOrder);
return inOrder.toString();
}
private void inOrderRecursively(Tree Node, List<Tree> inOrder) {
if (Node.mLeft != null) {
inOrderIt(Node.mLeft, inOrder);
}
inOrder.add(Node);
if (Node.mRight != null) {
inOrderIt(Node.mRight, inOrder);
}
}
greetings
I am having a few problems in my AVL tree implementation.. The code for all the rotations and the adding all seem to be correct and I dry-run the program to thoroughly check that it is running logically correct. I seem to be having a problem in my tree traversal (in-order) because it only outputs a few integers from the supposed 100. Also the search is always failing, regardless of what I enter. I cannot seem to grasp what is going on but I suspect that it has something to do with a few null pointers. Below is the code for the AVL tree, I am wondering if there's any incorrect code in the AddNode method or the rotation methods but they seem to be fine.. The classes are Node class, AVL class and AVL tree class which is the main class.
Node class
private int data;
private Node left;
private Node right;
private int height;
public Node(int m) {
data = m;
left = null;
right = null;
height = 0;
}
public void setToleft(Node newleft) {
left = newleft;
}
public Node getleftNode() {
return left;
}
public void setToright(Node newright) {
right = newright;
}
public Node getrightNode() {
return right;
}
public int getData() {
return data;
}
public int getHeight(){
return height;
}
public void setHeight(int height){
this.height = height;
}
AVL class
public Node root;
public AVL(int root) {
this.root = new Node(root); // since root presently has no left or right children, height is currently 0
}
public int Height(Node n) {
if (n == null) { //basis step
return -1;
} else { //add one for every path
if (n.getleftNode() == null && n.getrightNode() == null) {
return 0;
}
return 1 + Math.max(Height(n.getleftNode()), Height(n.getrightNode()));
}
}
public void add(int data) {
addNode(data, root);
root.setHeight(Math.max(Height(root.getleftNode()), Height(root.getrightNode())) + 1);
}
public void addNode(int data, Node n) {
if (data < n.getData()) {
if (n.getleftNode() == null) {
n.setToleft(new Node(data));
} else {
addNode(data, n.getleftNode());
}
n.setHeight(Math.max(Height(n.getleftNode()), Height(n.getrightNode())) + 1);
if ((Height(n.getleftNode()) + 1) - (Height(n.getrightNode()) + 1) == Math.abs(2)) {
if (data < n.getleftNode().getData()) {
n = LLRotation(n);
} else {
n = LRRotation(n);
}
}
} else if (data >= n.getData()) { //>= also caters for duplicates and inserts them infront of same value
if (n.getrightNode() == null) {
n.setToright(new Node(data));
} else {
addNode(data, n.getrightNode());
}
n.setHeight(Math.max(Height(n.getleftNode()), Height(n.getrightNode())) + 1);
if ((Height(n.getrightNode()) + 1) - (Height(n.getleftNode()) + 1) == Math.abs(2)) {
if (data >= n.getrightNode().getData()) {
n = RRRotation(n);
} else {
n = RLRotation(n);
}
}
}
}
public Node LLRotation(Node n) { //single
Node n1 = n.getleftNode();
n.setToleft(n1.getrightNode());
n1.setToright(n);
n.setHeight(Math.max(Height(n.getleftNode()), Height(n.getrightNode())) + 1);
n1.setHeight(Math.max(Height(n1.getleftNode()), Height(n)) + 1);
//compares heights of left and right subtrees and gets max
//the above source code is of course vital since the node height must be resetted after rotations
//adding 1 at the end of the last two code lines is important since
//initially the height is only calculated from subtrees onwards
//same for single right rotation below
return n1;
}
public Node RRRotation(Node n) { //single
Node n1 = n.getrightNode();
n.setToright(n1.getleftNode());
n1.setToleft(n);
n.setHeight(Math.max(Height(n.getleftNode()), Height(n.getrightNode())) + 1);
n1.setHeight(Math.max(Height(n1.getrightNode()), Height(n)) + 1);
return n1;
}
public Node LRRotation(Node n) { //double
n.setToleft(RRRotation(n.getleftNode()));
return LLRotation(n);
}
public Node RLRotation(Node n) { //double
n.setToright(LLRotation(n.getrightNode()));
return RRRotation(n);
}
public void inOrderTraversal(Node n) {
if (n != null) {
inOrderTraversal(n.getleftNode()); //recursive call to the left subtree
System.out.println(n.getData()); //line which makes the actual node to display its data
inOrderTraversal(n.getrightNode()); //recursive call to the right subtree
}
}
public void traverse() {
inOrderTraversal(root); // can be called in main class to automatically traverse tree from its root
}
public int search(int x) {
try {
if (x == root.getData()) { //basis step
System.out.println("Item found!");
return x;
}
if (x < root.getData()) {
root = root.getleftNode();
return search(x);//recursive call
} else {
root = root.getrightNode();
return search(x);//recursive call
}
} catch (NullPointerException e) {
System.out.println ("Search failed!");
return 0;
}
}
Main Class
public static void main(String[] args) throws IOException {
Scanner s = new Scanner(System.in);
AVL tree = null;
int choice = 0;
System.out.println("AVL TREE");
System.out.println("\n Choose an option from the menu: ");
System.out.println("\n\t 1.) Create file of 100 integers");
System.out.println("\n\t 2.) Create the tree");
System.out.println("\n\t 3.) In-Order traverse and show tree");
System.out.println("\n\t 4.) Search for integer");
System.out.println("\n\t 5.) Quit");
while (choice != 5) {
System.out.print("\nChoice: ");
choice = s.nextInt();
switch (choice) {
case 1:
createFile();
break;
case 2:
try {
FileReader readto = new FileReader("Integers.txt");
BufferedReader br = new BufferedReader(readto);
String line = br.readLine(); //reads text at start of file
line = br.readLine(); // skipping empty lines
line = br.readLine();
line = br.readLine();
int root = Integer.parseInt(line); //extracts first integer from the line
System.out.println("Root: " + root);
tree = new AVL(root);
int x = 0;
while (x != 99) {
try {
line = br.readLine();
int next = Integer.parseInt(line);
tree.add(next);
System.out.println(next);
x++;
} catch (NumberFormatException e) {
};
}
System.out.println("Tree successfully populated!");
} catch (FileNotFoundException e) {
System.out.println("ERROR: File not found!");
}
break;
case 3:
System.out.println("In-Order traversel executed. The now balanced tree shall now be printed in");
System.out.println("ascending order and also the left and right children of each node shall be printed.\n");
System.out.println("Traversal: ");
tree.traverse();
break;
case 4:
System.out.print("Please enter the integer to be searched: ");
int x = s.nextInt();
System.out.println(tree.search(x));
break;
case 5:
System.exit(0);
break;
default:
System.out.println("ERROR: Choice out of bounds!");
}
}
}
static void createFile() throws IOException {
Random r = new Random();
File intfile = new File("Integers.txt");
FileWriter writeto = new FileWriter("Integers.txt");
BufferedWriter bw = new BufferedWriter(writeto);
if (!(intfile.exists())) {
System.out.println("ERROR: File not found!");
} else {
bw.write("The following integers are randomly generated");
bw.newLine();
bw.write("and will be used to construct the AVL tree:");
bw.newLine();
bw.newLine();
int x;
System.out.println("The following random numbers shall be used to build the AVL tree: \n");
for (int i = 0; i < 100; i++) {
x = r.nextInt(100) + 1;
bw.write(String.valueOf(x));
bw.newLine();
System.out.println(x);
}
bw.close();
}
}
The output for the traversal is just the following:
Traversal:
44
53
54
54
77
Suppose that there were 100 integers entered and among them were these. But the output for the traversal was only this.
Output for the search is like this:
Choice: 4
Please enter the integer to be searched: 44
Item found!
44
Choice: 4
Please enter the integer to be searched: 100
Search failed!
0
100 and 44 were both integers added to the tree, but 44 was found and 100 wasn't.. I don;t understand..
Anyone can guide me to a solution..?
Thanks in advance :)
Well, first the obvious thing... In your search method, you are abusing the root variable, which holds the root of your tree, setting it to new values as your search proceeds. So, after the first search, root points to the last node traversed in the search and no longer to the root node of the tree. All following searches are unlikely to find anything at all from that point on.
As your search is recursive, try passing on the node-to-be-searched-in as parameter:
int search(Node node, int key) {
if (node == null) {
return 0; // missing from tree
} else if (key < node.getData()) {
return search(node.getLeft(), key);
} else if (key > node.getData()) {
return search(node.getRight(), key);
} else {
return node.getData(); // found it
}
}
(Edited to address the comments) You might have to expose this method like you do with your add/addNode method pair using a publicly available wrapper, and an internal implementation:
public int search(int key) {
return searchNode(root, key);
}
private int searchNode(Node node, int key) {
// Perform the recursive search, as above
}
There are other problems related to your add/addNode methods. Maybe I just overlooked it, but nowhere do you adjust the root node of your tree, if rotation would make it necessary. This, in effect, causes your tree to get out of balance, losing the AVL property over time.
I'm trying to work on a method that will insert the node passed to it before the current node in a linked list. It has 3 conditions. For this implementation there cannot be any head nodes (only a reference to the first node in the list) and I cannot add any more variables.
If the list is empty, then set the passed node as the first node in the list.
If the current node is at the front of the list. If so, set the passed node's next to the current node and set the first node as the passed node to move it to the front.
If the list is not empty and the current is not at the front, then iterate through the list until a local node is equal to the current node of the list. Then I carry out the same instruction as in 2.
Here is my code.
public class LinkedList
{
private Node currentNode;
private Node firstNode;
private int nodeCount;
public static void main(String[] args)
{
LinkedList test;
String dataTest;
test = new LinkedList();
dataTest = "abcdefghijklmnopqrstuvwxyz";
for(int i=0; i< dataTest.length(); i++) { test.insert(new String(new char[] { dataTest.charAt(i) })); }
System.out.println("[1] "+ test);
for(int i=0; i< dataTest.length(); i++) { test.deleteCurrentNode(); }
System.out.println("[2] "+test);
for(int i=0; i< dataTest.length(); i++)
{
test.insertBeforeCurrentNode(new String(new char[] { dataTest.charAt(i) }));
if(i%2 == 0) { test.first(); } else { test.last(); }
}
System.out.println("[3] "+test);
}
public LinkedList()
{
setListPtr(null);
setCurrent(null);
nodeCount = 0;
}
public boolean atEnd()
{
checkCurrent();
return getCurrent().getNext() == null;
}
public boolean isEmpty()
{
return getListPtr() == null;
}
public void first()
{
setCurrent(getListPtr());
}
public void next()
{
checkCurrent();
if (atEnd()) {throw new InvalidPositionInListException("You are at the end of the list. There is no next node. next().");}
setCurrent(this.currentNode.getNext());
}
public void last()
{
if (isEmpty()) {throw new ListEmptyException("The list is currently empty! last()");}
while (!atEnd())
{
setCurrent(getCurrent().getNext());
}
}
public Object getData()
{
return getCurrent().getData();
}
public void insertBeforeCurrentNode(Object bcNode) //beforeCurrentNode
{
Node current;
Node hold;
boolean done;
hold = allocateNode();
hold.setData(bcNode);
current = getListPtr();
done = false;
if (isEmpty())
{
setListPtr(hold);
setCurrent(hold);
}
else if (getCurrent() == getListPtr())
{
System.out.println("hi" + hold);
hold.setNext(getCurrent());
setListPtr(hold);
}
else //if (!isEmpty() && getCurrent() != getListPtr())
{
while (!done && current.getNext() != null)
{
System.out.println("in else if " + hold);
if (current.getNext() == getCurrent())
{
//previous.setNext(hold);
//System.out.println("hi"+ "yo" + " " + getListPtr());
hold.setNext(current.getNext());
current.setNext(hold);
done = true;
}
//previous = current;
current = current.getNext();
}
}
System.out.println(getCurrent());
}
public void insertAfterCurrentNode(Object acNode) //afterCurrentNode
{
Node hold;
hold = allocateNode();
hold.setData(acNode);
if (isEmpty())
{
setListPtr(hold);
setCurrent(hold);
//System.out.println(hold + " hi");
}
else
{
//System.out.println(hold + " hia");
hold.setNext(getCurrent().getNext());
getCurrent().setNext(hold);
}
}
public void insert(Object iNode)
{
insertAfterCurrentNode(iNode);
}
public Object deleteCurrentNode()
{
Object nData;
Node previous;
Node current;
previous = getListPtr();
current = getListPtr();
nData = getCurrent().getData();
if (isEmpty()) {throw new ListEmptyException("The list is currently empty! last()");}
else if (previous == getCurrent())
{
getListPtr().setNext(getCurrent().getNext());
setCurrent(getCurrent().getNext());
nodeCount = nodeCount - 1;
}
else
{
while (previous.getNext() != getCurrent())
{
previous = current;
current = current.getNext();
}
previous.setNext(getCurrent().getNext());
setCurrent(getCurrent().getNext());
nodeCount = nodeCount - 1;
}
return nData;
}
public Object deleteFirstNode(boolean toDelete)
{
if (toDelete)
{
setListPtr(null);
}
return getListPtr();
}
public Object deleteFirstNode()
{
Object deleteFirst;
deleteFirst = deleteFirstNode(true);
return deleteFirst;
}
public int size()
{
return this.nodeCount;
}
public String toString()
{
String nodeString;
Node sNode;
sNode = getCurrent();
//System.out.println(nodeCount);
nodeString = ("List contains " + nodeCount + " nodes");
while (sNode != null)
{
nodeString = nodeString + " " +sNode.getData();
sNode = sNode.getNext();
}
return nodeString;
}
private Node allocateNode()
{
Node newNode;
newNode = new Node();
nodeCount = nodeCount + 1;
return newNode;
}
private void deAllocateNode(Node dNode)
{
dNode.setData(null);
}
private Node getListPtr()
{
return this.firstNode;
}
private void setListPtr(Node pNode)
{
this.firstNode = pNode;
}
private Node getCurrent()
{
return this.currentNode;
}
private void setCurrent(Node cNode)
{
this.currentNode = cNode;
}
private void checkCurrent()
{
if (getCurrent() == null) {throw new InvalidPositionInListException("Current node is null and is set to an invalid position within the list! checkCurrent()");}
}
/**NODE CLASS ----------------------------------------------*/
private class Node
{
private Node next; //serves as a reference to the next node
private Object data;
public Node()
{
this.next = null;
this.data = null;
}
public Object getData()
{
return this.data;
}
public void setData(Object obj)
{
this.data = obj;
}
public Node getNext()
{
return this.next;
}
public void setNext(Node nextNode)
{
this.next = nextNode;
}
public String toString()
{
String nodeString;
Node sNode;
sNode = getCurrent();
//System.out.println(nodeCount);
nodeString = ("List contains " + nodeCount + " nodes");
while (sNode != null)
{
nodeString = nodeString + " " +sNode.getData();
sNode = sNode.getNext();
}
return nodeString;
}
}
}
I have it working for my [1] and [2] conditions. But my [3] (that tests insertBeforeCurrentNode()) isn't working correctly. I've set up print statements, and I've determined that my current is reset somewhere, but I can't figure out where and could use some guidance or a solution.
The output for [1] and [2] is correct. The output for [3] should read
[3] List contains 26 nodes: z x v t r p n l j h f d b c e g i k m o q s u w y a
Thanks for any help in advance.
In your toString method you start printing nodes from the currentNode till the end of your list. Because you call test.last() just before printing your results, the currentNode will point on the last node of the list, and your toString() will only print 'a'.
In your toString() method, you may want to change
sNode = getCurrent();
with
sNode = getListPtr();
to print your 26 nodes.
For [3] you need to keep pointers to two nodes: one pointer in the "current" node, the one you're looking for, and the other in the "previous" node, the one just before the current. In that way, when you find the node you're looking in the "current" position, then you can connect the new node after the "previous" and before the "current". In pseudocode, and after making sure that the cases [1] and [2] have been covered before:
Node previous = null;
Node current = first;
while (current != null && current.getValue() != searchedValue) {
previous = current;
current = current.getNext();
}
previous.setNext(newNode);
newNode.setNext(current);