Unable to set reference variable in recursive call - java

I am using a recursive method to find a node in a binary tree using a key. When I find the node, I set it to my reference variable foundNode and return. The problem is that when I read the object its value is still null. Can anybody help?
findGivenNode(root, key, foundNode, parentStack);
private boolean findGivenNode(Node node, int key, Node foundNode, Stack<Node> parentStack) {
if (node == null) {
return false;
}
parentStack.add(node);
if (node.getData() == key) {
foundNode = node;
return true;
}
boolean leftReturn = findGivenNode(node.getLeftChild(), key, foundNode, parentStack);
boolean RightReturn = findGivenNode(node.getRightChild(), key, foundNode, parentStack);
if (leftReturn || RightReturn) {
return true;
} else {
parentStack.pop();
return false;
}
}

Java doesn't pass arguments by reference, they are passed by value. Read more here
Let's clarify by an example. Make the key you are looking for be integer with value 21.
The situation at the beginning of the function is the following:
So now, when you say:
foundNode = node; // this doesn't reflect outside of the method
You are changing the value of foundNode locally inside the findGivenNode() method, it doesn't apply to outside this method. Basically, the local variable called foundNode references the node you want to change and then you make this local variable foundNode reference the new node by the statement above.
This change is reflected only inside the function. As soon as your function is finished, local variables don't exist anymore so neither does this local version of foundNode. Visual result:
The simple solution is to use a Wrapper function
To keep track of the reference, you can make a simple wrapper class that will store the reference you want:
private class NodeWrapper {
Node foundNode;
NodeWrapper() {
foundNode = null;
}
}
Then you can create a new NodeWrapper and pass that into your function instead of foundNode
NodeWrapper wrapper = new NodeWrapper();
findGivenNode(root, wrapper, key, parentStack);
Then inside your function instead of:
foundNode = node;
You say:
wrapper.foundNode = node;
This way you can maintain the reference throughout the recursion inside the NodeWrapper. Meaning:
NodeWrapper wrapper = new NodeWrapper();
findGivenNode(root, wrapper, key, parentStack);
// at this point, wrapper.foundNode will hold the reference to the node you need
// or null if the node wasn't found
On another note, above the method you have this function prototype:
findGivenNode(root, key, foundNode, parentStack);
Seems like someone is still used to C/C++ :)
This is unnecessary in Java, you can read this question thread for reasoning behind that or just Google it.

Related

Remove All Occurrences of a Given Value from a Doubly Linked List

Alright, so cut a long story short, what I'm trying to do here is remove all instances of value e from a doubly linked list. As far as I know, my logic is at least mostly right, but for some off reason it isn't actually removing any of the nodes in my test cases.
public boolean removeAll(int e) {
DIntNode dummy = head,next = null;
if (head == null)
return false;
while (dummy != null) {
if (dummy.getData() == e) {
next = dummy.getNext();
dummy.getNext().setPrev(null);
dummy = next;
return true;
}
else
dummy = dummy.getNext();
}
return false;
}
This is what I currently have for my code of the metho. My logic here was to use a dummy DIntNode that starts at the head and a "next" node to help me shrink the list, so to speak. In other words, if the list was something like "1<-> 1 <-> 2 <-> 3", the function would change it to "2<->3", in theory. The reason this is a boolean function is because I'm required to return true if the given value is removed form the list.
Is there just another step in the logic that I'm missing, or is the methodology itself just unreliable? I'm very unsure at this point, so any and all help would be greatly appreciated.
You set
dummy.getNext().setPrev(null);
But previous node also have reference to next node you try to remove. You should set this reference to next active value.
That because when you want to get all linked list previous value still know about node you remove, because of next node reference
You can try with the following code:
if (dummy.getData() == e) {
DIntNode temp = dummy.getPrevious();
temp.next = dummy.getNext();
temp = dummy.getNext();
temp.previous = dummy.getPrevious();
return true;
}
This used the previous reference. So the previous node will now have reference to the next node of your dummy node (node to be deleted). And similarly, the next node of dummy node will have reference of previous node of your dummy node. So, the dummy node will loose its connection/link from its doubly link list and that's what we want!
Please try.
Two issues with the code:
When relinking a doubly linked list, where removing B from A - B - C, you need to set the next node for A to be C as well as the previous node for C to be A. With trying to keep you method names:
A.setNext(current.getNext());
C.setNext(current.getPrev());
With your code, if you find an occurrence, you return, which means that no other instances will be removed since you jump out of that method. You will probably need a new boolean removed variable, that is set to false, return true changed to removed = true and return false changed to return removed.
The method exits after the first encounter of 'e'.
If you want to remove all instances of 'e', then you should have something like this:
boolean listChanged = false;
while (dummy != null) {
if (dummy.getData() == e) {
// update list
...
listChanged = true;
}
...
}
return listChanged;
Also, you should not write your code like this:
dummy.getNext().setPrev(...); // throws NPE if next is null

Remove Method in HashTable

Hi I'm working on an assignment about hash table. Everything is fine except for the remove method.
Here's code:
public boolean remove(K key) throws HashTableException {
//
//IMPLEMENT THIS FUNCTION
//
if (key == null)
throw new HashTableException("Null keys not allowed in the hash table");
int index = getIndex(key);
HashTableNode<K,V> node = FindNode(key,index);
if (node == null) {
return false;
} else {
if (node.getNext() == null) {
node = null;
} else {
node = node.getNext();
}
return true;
}
}
It doesn't remove the key at all. Can anyone help me please? thank you!
node = null; does not "delete" the node, it just sets the value of the variable node in this method to null. It does nothing to the actual node that is in the hashtable somewhere.
And in the next "else" you then have node = node.getNext(); which, again, only change the node variable in this method. But since you return from the method without doing anything more with this variable, all this does is nothing since node is a local variable that only exists in this method.
You should read up on the concepts of local variables and references in java, which would probably lead to an understanding of why this is not working :)
node = node.getNext();
By this line, I think you are just traversing instead of re-writing the Next pointer
Maybe you should try node.getPrev().setNext = node.getNext();
if you can find the previous node and be able to set the next node.
Please make sure hashcode() and equals() are overridden correctly.

Setting myself to null - Java

I came across the following problem:
Delete a node in the middle of a singly linked list, given only access to that node. (head is not given)
Now there are a lot of solutions and they all do not work when the element to be deleted is the last node.
Why wouldn't this work?
public static void removeNode (Node n){
if(n.next == null){ //n is the last node
n= null;
return;
}
//handling general case here
}
Java passes parameters by value, so setting n to null has no effect outside of the method. This means the method essentially does nothing when passed the last node of a list.
You need to set null the reference in the previous node, not the variable that references to your last node, something like this:
if(n.next == null) {
prev.next = null;
return;
}
n is local to the method, so changing its value won't affect the list itself. You need to modify the next of the previous node, which you do not have access to.

Confused about linked list deletion

I am trying to implement the deletion function in
public static boolean delete(Object d, ListElement head){
ListElement p=find(d,head);
if(p.data==null){return false;}
else {
System.out.println("Delete Successfully!");
if(head.data==d){head=head.next;}
else{
while(head.next.data!=d){
head=head.next;
}
head.next=head.next.next;}
return true;}
}
This function basically check if the element d is in the list,
-if not->return false;
-else check whether the element is the first element of the list, if true, change the head to its next,
-else traverse to the list element in front of it.
The problem is case the element to delete is the first element, such as boolean s=ListElement.delete(1,d); I cannot use "head=head.next;" to assign new value to head. But java is passed by reference, why cannot I change that?
//actually I found my question is whether we can change the reference passed to the function inside the function
like:
void fun(dog a){
a=new dog("Po");
}
main()
{dog b=new dog("Jo");fun(b);}
//so will b be changed?
The reference to the first list element is either held by the list object itself or by an "invisible" root element (in case of single linked list).
So you either have to pass the entire list to the method or, if you have that invisible root, pass the root as head.
public static boolean delete(Object d, MyLinkedList<ListElement> list) {
ListElement head = list.getHead();
if (head.data.equals(d)) { // <- ALWAYS use equals, never == to compare objects!!
list.setHead(head.next);
} else {
ListElement element = head.next;
// ... the rest is similiar to your algorithm
}
}
The Java Pass by Reference idea means, that when you call a method, and give some object as an argument, you'll get a new reference pointing to the same object.
Altering values, will change the object, in turn also affecting other references. But if you give a new value to the parameter, only that will be changed, to point to some different object. (It's worth mentioning that there are languages that do allow changing the argument, to change the first passed parameter.)
void delete(visit_ptr_node_type this_is_the_node)
{
visit_ptr_node_type one_back;
if(anchor == NULL)
printf("\n The list is empty");
else
{
if(this_is_the_node==anchor)
anchor=anchor->next_ptr;
else
{
one_back=anchor;
while(one_back->next_ptr != this_is_the_node)
one_back=one_back->next_ptr;
one_back->next_ptr = (this_is_the_node) ->next_ptr;
}
free(this_is_the_node);
}
}

How do I add an object to a binary tree based on the value of a member variable?

How can I get a specific value from an object?
I'm trying to get a value of an instance
for eg.
ListOfPpl newListOfPpl = new ListOfPpl(id, name, age);
Object item = newListOfPpl;
How can I get a value of name from an Object item??
Even if it is easy or does not interest you can anyone help me??
Edited: I was trying to build a binary tree contains the node of ListOfPpl, and need to sort it in the lexicographic. Here's my code for insertion on the node. Any clue??
public void insert(Object item){
Node current = root;
Node follow = null;
if(!isEmpty()){
root = new Node(item, null, null);
return;
}boolean left = false, right = false;
while(current != null){
follow = current;
left = false;
right = false;
//I need to compare and sort it
if(item.compareTo(current.getFighter()) < 0){
current = current.getLeft();
left = true;
}else {
current = current.getRight();
right = true;
}
}if(left)
follow.setLeft(new Node(item, null, null));
else
follow.setRight(new Node(item, null, null));
}
Since your item variable is declared to be of the most basic Java type Object, you can't extract anything related to your data from it directly. The variable newListOfPpl, on the other hand, which is a reference to the same object, is declared to be of type ListOfPpl, so you can invoke on it whatever getter methods that have been defined in it (possibly getId(), getName(), getAge()).
That all depends on what ListOfPpl 'has inside it'.
Does it have a method to access it's data? or public data members?
For example, if ListOfPpl had a .getname() method.
Without knowing more about ListOfPpl I don't think I can be off much more help sorry.
Hope this was useful to you, and goodluck!

Categories