I am currently trying to implement a dictionary using a search tree. (The exercise tells me to use such a structure). My tree is made out of nodes that save 2 strings: abreviere(the abreviation of a phrase) and acronim(the phrase). Here is my implementation so far:
Node Class:
public class Nod {
String acronim;
String abreviere;
Nod st,dr;
Nod(String acronim,String abreviere){
this.acronim = acronim;
this.abreviere = abreviere;
st = null;
dr = null;
}
}
Tree Class:
Constructor and insert:
public class Arbore {
Nod root;
Arbore(Nod x){
root = x;
}
public void insert(Nod x,Nod curr){
if(curr.acronim.compareTo(x.acronim) < 0){
if(curr.st == null){
curr.st = new Nod(x.acronim,x.abreviere);
}
else insert(x,curr.st);
}
else if(curr.dr == null){
curr.dr = new Nod(x.acronim, x.abreviere);
}
else insert(x,curr.dr);
}
}
I made them to work. I don't understand why I can't have this code instead:
public class Arbore {
Nod root;
Arbore(){
}
public void insert(Nod x,Nod curr){
if(curr == null) {curr = x; return;}
if(curr.acronim.compareTo(x.acronim) < 0){
if(curr.st == null){
curr.st = new Nod(x.acronim,x.abreviere);
}
else insert(x,curr.st);
}
else if(curr.dr == null){
curr.dr = new Nod(x.acronim, x.abreviere);
}
else insert(x,curr.dr);
}
This wouldn't save my structure either (I am clearly missing something and seems to be related). The problem I am facing now is deleting a node. I have to search for an abreviation(abreviere) and if I find it I must print the phrase and delete the node. These are the methods that I use to do this:
public void search(String acronim){
if(root.acronim.compareTo(acronim) == 0) delete(root);
if(root.acronim.compareTo(acronim) < 0) search(acronim,root.st);
if(root.acronim.compareTo(acronim) > 0) search(acronim,root.dr);
}
private void search(String acronim,Nod curr){
if(curr == null){System.out.println("Nu exista"); return;}
if(curr.acronim.compareTo(acronim) == 0) this.delete(curr);
if(curr.acronim.compareTo(acronim) < 0) this.search(acronim,curr.st);
if(curr.acronim.compareTo(acronim) > 0) this.search(acronim,curr.dr);
}
private void delete(Nod x){
if(x.st == null && x.dr == null){ x = null; System.out.println("deleting");}
else if(x.st == null && x.dr != null) {x = x.dr;System.out.println("deleting right");}
else if(x.st != null && x.dr == null) {x = x.st;System.out.println("deleting left");}
else{
System.out.println("Il deletez");
Nod aux = new Nod(x.acronim,x.abreviere);
x.abreviere = x.st.abreviere;
x.acronim = x.st.acronim;
x.st.abreviere = aux.abreviere;
x.st.acronim = aux.acronim;
delete(x.st);
}
}
They seem to do the job(from the printed messages) . However the changes don't save, after I apply the method I am left with the same tree. Here is the printing method that shows me the current tree:
public String inordine(Nod root){
if(root == null) return "";
return inordine(root.st) + afis(root) + inordine(root.dr);
}
private String afis(Nod n){
if(n == null) return "E nula?!";
return n.abreviere + "->" + n.acronim + "\n";
}
public void afisare(){
System.out.println(inordine(this.root));
}
What am I doing wrong? Is it the garbage collector or something? I use my class like this:
public static void main(String[] args) throws FileNotFoundException, IOException {
FileReader fr = new FileReader("Acronime.txt");
BufferedReader bf = new BufferedReader(fr);
String line = bf.readLine();
String[] array = line.split("=>");
Nod x = new Nod(array[0],array[1]);
Arbore a = new Arbore(x);
while((line = bf.readLine()) != null){
String[] array2 = line.split("=>");
Nod y = new Nod(array2[0],array2[1]);
a.insert(y,a.root);
}
a.afisare();
a.search("JSE");
a.afisare();
}
The words come like this but this part works .
JSE=>JavaScript Encoding
ESP=>Enhanced Serial Port
MSB=>Most Significant Byte
CDRAM=>Cached Dynamic RAM
EMI=>Electro-Magnetic Interference
CDRAM=>Cached Dynamic RAM
AIFF=>Audio Interface File
BASM=>Built in AsseMbler
After looking at the suggested post I changed 2 rows in the delete method and added 1 more method:
Changed Rows:
else if(x.st == null && x.dr != null) {copy(x,x.dr); x.dr = null; System.out.println("deleting right");}
else if(x.st != null && x.dr == null) {copy(x,x.st); x.st = null; System.out.println("deleting left");}
This way the changes stick(if you want to know why read the question from the suggested post below).
In the end the question is : "How to delete an instance of a class because you can't do it with x = null;? "
About the constructor:
In the method you would like to use (with the empty constructor) you need to set the class member root at some point. Something like this should do it:
public void insert(Nod x,Nod curr){
if(curr == null) {
this.root = x;
return;
}
...
About deletion
I don't understand the case when st and dr is not null. You seem to keep the tree structure intact but switch the payload data (abreviere, acronim) of the st side and then delte the st node. I don't get it yet. I will update my answer when I understand better.
You can't destroy an instance of a class in java like I was trying to do in the delete method if(x.st == null && x.dr == null){ x = null;} . To delete the node from the tree you have to find the parent of x and then parent.x = null. This way the reference to x is lost and the garbage collector does his job.
This is because , like #Seelenvirtuose said, java uses pass-by-value which you can read more about in the link that he provided: click!
Related
This question already has answers here:
What is a NullPointerException, and how do I fix it?
(12 answers)
Closed 1 year ago.
I have a Java task where I have to create a splay tree which requires me to find the parent and grandparent node of the node I am accessing. To do this, I've chosen to create a findParent method. Here is my Node class.
public class Node<T>
{
public T elem = null;
public Node<T> left = null;
public Node<T> right = null;
public Node(T elem) {
this.elem = elem;
}
public String toString() {
String out = elem.toString();
out += " [L: "+ (left == null ? "null" : left.elem) + "] ";
out += " [R: "+ (right == null ? "null" : right.elem) + "] ";
return out;
}
}
I am not allowed to change the Node class. My SplayTree class is made up of these nodes and inside the SplayTree class, I have my findParent function.
public Node<T> findParent(Node<T> A) {
Node<T> P = root;
if (P.left == A || P.right == A) {
return P;
} else if (A.elem.compareTo(P.elem) < 0) {
P = P.left;
} else {
P = P.right;
}
return null;
}
To test the code, I've entered the following numbers in order into the tree "50, 25, 100, 5, 110, 115, 75, 42, 101, 112". The insert method follows the normal BST insert rules of having larger elements on the right and smaller elements on the left. I tested my findParent method using the node containing 110 as the target so theoretically, it should return 100 as the parent and to get the grandparent, I would use findParent(parent) which should return 50 but instead, I get a nullptr exception. I've tested my insert function to see if I am populating my tree correctly, however, that is not the case as the insert method works correctly.
you can do it recursively but it may crashes the executing thread with StackOverFlow exception on large data sets
public Node<T> findParent(Node<T> node, Node<T> n){
if(node == null) return null;
if(node.right == n || node.left == n){
return node;
}else{
Node<T> r = findParent(node.left, n);
if(r == null){
r = findParent(node.right, n);
}
return r;
}
}
public Node<T> findParent(Node<T> n){
if(n == null)
throw new NullPointerException("arg0 cannot be Null");
return findParent(root, n);
}
for large data sets you should have some sort of Stack machine to traverse all the nodes:
public Node<Object> findParent(Node<T> root, Node<T> node){
Stack<Node<T>> stack = new Stack<>();
stack.push(root);
while(stack.size() > 0){
Node<T> p = stack.pop();
if(p.right == node || p.left == node){
return p;
}else{
if(p.left != null){
stack.push(p.left);
}else if(p.right != null){
stack.push(p.right);
}else{
Node<T> parent = null;
if(stack.size() > 0)
parent = stack.peek();
if(parent == null){
break;
}else if(parent.left == p){
if(parent.right != null){
stack.push(parent.right);
}
}else if(parent.right == p){
stack.pop();
}
}
}
}
return null;
}
both tested with your data structure.
in the second example at line 10, if you return the Stack<Node> you can have all the parents in a row
I've been staring at this forever, and neither my tutor nor classmates were able to find what might be happening. Any help at all would be so appreciated!
I have an error in my binary tree program somewhere that is causing for the lefthand leaf to be printed repeatedly and the righthand leaf to be skipped, but I can't figure out where it might be.
The assignment specifies the design and method signatures that we're to use, as well as using recursion in certain methods, so I can't change any of that. Each node has an array of up to two child nodes.
We need to format the printing so that each node is printed on the same line as its children.
For example:
Node rootNode = new Node("A");
rootNode.addChild("B", "A");
rootNode.addChild("E", "A");
rootNode.addChild("F","E");
rootNode.addChild("H","E");
rootNode.addChild("C", "B");
rootNode.addChild("D", "B");
rootNode.printTree();
Should return:
ABE
BCD
C
D
EFH
F
H
But is instead printing:
ABE
BCC
C
C
EFH
F
H
Node "D" is missing while "C" is getting reprinted, but somehow Node "H" (also the righthand leaf just like "D", but on the right branch instead of the left) is still getting printed correctly. When I use my find() method on "D" it returns null which seems to indicate it isn't getting put in the tree, so I think the error is in my addChild() method. I just can't for the life of me find where it is.
public boolean addChild(String ID, String parentID) {
if(myID.equals(parentID)) { // found parent
if(children[0] == null) {
children[0] = new Node(ID, find(parentID));
numberOfChildren++;
return true;
}
if (children[1] == null) {
children[1] = new Node(ID, find(parentID));
numberOfChildren++;
return true;
}
else {
// System.out.println("This is already full.");
return false;
}
}
else
{
if(numberOfChildren == 0) {
return false;
}
else if(numberOfChildren == 1) {
return children[0].addChild(ID, parentID);
}
else {
if(children[0].addChild(ID, parentID) == false) {
return children[1].addChild(ID, parentID);
}
else {
return children[0].addChild(ID, parentID);
}
}
}
}
Otherwise, the issue might be in the toString/print method:
public String toString() {
String childOne = "";
String childTwo = "";
if (children[0] != null) {
childOne = children[0].getId();
}
if(children[1] != null) {
childTwo = children[1].getId();
}
return(myID + childOne + childTwo);
}
#Override
public void printTree() {
// TODO Auto-generated method stub
System.out.println(toString() + " ");
if(children[0] != null) {
children[0].printTree();
}
if(children[1] != null) {
children[1].printTree();
}
}
}
Thank you in advance!!
I want to write a method that allows me to insert a value to the list (generic implementation). Furthermore i want to check wether a value in already in the list or not. I just want to know wether this is how its supposed to be or not.
In order to check wether a value is already contained within the list:
public boolean contains(T value) {
boolean searchedValue;
if (head == null || baseListLength == 0) {
searchedValue= false;
} else {
IndexListEntry<T> blub= head;
while ((blub.next != null) && (blub.next.value.compareTo(value) <= 0)) {
value= blub.next;
}
searchedValue= baseList.contains(value, blub.pointer);
}
return searchedValue;
}
and to add any value to the list:
public boolean addValue(T value) {
BaseListEntry<T> offs= baseList.add(value);
if (indexListLength < indexMaxLength) {
if (head == null) {
head = new IndexListEntry<T>(value, null, offs);
} else {
IndexListEntry<T> temp= head;
while ((temp.next != null) && (temp.next.value.compareTo(value) < 0)) {
temp= temp.next;
}
if (temp.next == null) {
temp.next = new IndexListEntry<T>(value, null, offs);
} else {
temp.next = new IndexListEntry<T>(value, temp.next, offs);
}
}
indexListLength++;
} else {
IndexListEntry<T> currentIndex = head.next;
int intervalWidth = baseListLength / indexMaxLength;
int intervalAdj = baseListLength % indexMaxLength;
int indexPosition = 0;
for (int i = 1; i < indexMaxLength; i++) {
int rip= 0;
if (intervalAdj - i >= 0)
rip= 1;
indexPosition = indexPosition + intervalWidth + rip;
BaseListEntry<T> newIndexTarget = baseList.getBaseListEntry(indexPosition);
currentIndex.pointer = newIndexTarget;
currentIndex.value = newIndexTarget.value;
currentIndex = currentIndex.next;
}
}
return true;
}
Are there any other methods to accomplish that goal? is my code somewhat correct. I am doubting everything I code right now and I kinda need confirmation from someone who knows more than me about this.
This is of course not everything i got. there are more classes to it but these are not the problem at hand so i dont thnk i need to upload that code as well.
I am trying to build an algorithm to find a node's successor, by recursively calling the following :
public static BTreeNode inorderFirst(BTree T) {
BTreeNode n = T.getRoot();
if (n == null)
return null;
while (n.getLeftChild() != null)
n = n.getLeftChild();
return n;
}
And calling this
public static BTreeNode inorderNext(BTreeNode n) {
//returns successor. if it finds one.
// TODO
// if node has a right child get its left descendant.
// otherwise get the first ancestor of which in the left sub-tree the node n is.
// if it didn't find
return null;
} // inorderNext()
I am using custom imports which have methods for getting getLeftChild(), and so on also has getParent() which aren't too hard to figure out. If anyone has any ideas on how to start building this. I have added some comments of my own plan. I just don't know how to start executing. I would like the structure because it makes it easier to test the method.
I figured out a way to make it work without using the recursion:
public static BTreeNode inorderNext(BTreeNode n) {
if (n.getRightChild() != null) {
BTreeNode temp = n.getRightChild();
while (temp.getLeftChild() != null)
temp = temp.getLeftChild();
return temp;
}
else {
BTreeNode temp = n;
BTreeNode par = n.getParent();
while (par != null) {
if (par.getLeftChild() == temp)
return par;
else {
temp = par;
par = par.getParent();
}
}
}
return null;
} // inorderNext()
But i am still wondering if there was a way to use the first function recursively on this one.
Your code would be something like the following:
if(n.getLeftChild() != null)
inorderNext(n.getLeftChild());
System.out.print(n.data);
if(n.getRightChild() != null)
inorderNext(n.getRightChild());
So basically i have this java project for school, and it requires me to read information from a text file, create an object from that information, and then insert that object into a hash table.
I am able to read the information from the text file and create the object, however, for some reason, my program isnt inserting the object into the hash table. Because then at the end of the program, when i try to search for the object (via its ID), it just returns 'not found'.
EDIT: My question is not how to compare strings. It is how to take the information from the text file, turn it into an object, and then insert it into the hash table. I know how to take the info and turn it into an object, but for some reason, it is not being inserted into the hashtable. Nothing i am inserting into the hashtable from the textfile is actually being inserted. That is the problem I am having.
This is the code i have written:
package test;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;
public class testmain {
public static void main(String[] args) throws FileNotFoundException{
StorageSystem ss = new StorageSystem();
ss.createhashtable();
String line;
String [] parts;
File in = new File("database.txt");
Scanner sc = new Scanner(in);
while(sc.hasNextLine()){
line = sc.nextLine();
parts = line.split(" ");
String type = parts[0];
String name = parts[1];
String id = parts[2];
String price = parts[3];
if(type.equals("Insert")){
Product p1 = new Product(name, id, Double.parseDouble(price));
ss.insert(p1);
}
else if(type.equals("remove")){
ss.remove(id);
}
}
sc.close();
System.out.println(ss.searchbyID("123"));
System.out.println(ss.searchbyID("232"));
System.out.println(ss.searchbyID("444"));
System.out.println(ss.searchbyID("456"));
//If i do it manually (below), it works. But thats not the point of this project
/*
Product ex = new Product("joe", "123", 22.33);
ss.insert(ex);
System.out.println(ss.searchbyID("123"));
ss.remove("123");
System.out.println(ss.searchbyID("123"));
*/
//When i do it this way ^^, it inserts the object into the hashtable, it
//searches for the object and finds it. it then removes the object. and
//when it searches again it doesnt find anything. And thats how it
//should work.
}
}
//Below is the class that contains the information on the hashtable
import java.io.*;
import java.util.Scanner;
public class StorageSystem {
private final static int tablesize = 1000;
private static Product[] table = new Product[tablesize];
public StorageSystem(){
table = new Product[tablesize];
for(int i = 0; i < tablesize; i++){
table[i] = null;
}
}
public void createhashtable(){
table = new Product[tablesize];
for(int i = 0; i < tablesize; i++){
table[i] = null;
}
}
public void useExistingTable(Product[] pt){
table = pt;
}
public String searchbyID(String idnum){
int hash = (Integer.parseInt(idnum) % tablesize);
if(table[hash] == null){
return "Not Found.";
}
else{
Product entry = table[hash];
while((entry != null) && (entry.getID() != idnum)){
entry = entry.getNext();
}
if(entry == null){
return "Not Found.";
}
else
return entry.toString();
}
}
public void insert(Product p){
String n = p.getName();
String i = p.getID();
double pr = p.getPrice();
int hash = (Integer.parseInt(i) % tablesize);
if(table[hash] == null){
table[hash] = new Product(n, i, pr);
}
else{
Product entry = table[hash];
while((entry.getNext() != null) && (entry.getID() != i)){
entry = entry.getNext();
}
entry.setNext(new Product(n, i, pr));
}
}
public void remove(String idnum) {
int hash = (Integer.parseInt(idnum) % tablesize);
if (table[hash] != null) {
Product prevEntry = null;
Product entry = table[hash];
while (entry.getNext() != null && entry.getID() != idnum) {
prevEntry = entry;
entry = entry.getNext();
}
if (entry.getID() == idnum) {
if (prevEntry == null)
table[hash] = entry.getNext();
else
prevEntry.setNext(entry.getNext());
}
}
}
}
If anyone could help me out with this problem that would be great. I have been looking at this thing for a few days now and cant get it to work.
entry.getID() != idnum
change to
!idnum.equals(entry.getID())
in case of entry.getID() returns null
entry.getID() == idnum
is also the same
==================
update:
Since you said the object is not insert into array. I guess it happens here:
There's an id let's say "100" in array. And you want to insert an Product with id "100", so it goes to
else{
Product entry = table[hash];
while((entry.getNext() != null) && (entry.getID() != i)){
entry = entry.getNext();
}
entry.setNext(new Product(n, i, pr));
}
You use entry.getID() != i or !i.equals(entry.getID(), both are ok. But in the end, you set new Product to entry.next.
But in your searchByID() method. You are trying to search through table[hash]
while((entry != null) && (entry.getID() != idnum)){
entry = entry.getNext(); // comment 1
}
if(entry == null){
return "Not Found.";
}
Issue happens here, entry is null will jump out the loop. It means when while loop is done, entry would always be null. You can set a breakpoint on comment 1.