How do you construct a JAVA recursive method Dequeue - java

Firstly, I have a linked list implementation of a Queue where Dequeuing occurs at the Head of the linked list. I have one no-argument no-return public method:
public void recursiveDequeue() {
head = recursiveDequeue(size()-1, head);
}
And a second method:
private Node recursiveDequeue(int index, Node current) {
if (current==null) {
// some code I need to write
}
return current;
}
I cannot for the life of me figure out how to do this. The only thing I can change is the comment that states clearly where I need to write code.
How do you build a recursion method that dequeues from the head but whose calling method already refers to the head? How is that even recursion? I dont even know what this is supposed to do.

Maybe something like the following. I don't know what exactly to do with index, seems superfluous here, but if it is the number of elements to dequeue as suggested in comments:
private Node recursiveDequeue(int index, Node current) {
if (current==null || index==0) {
return null;
}
return recursiveDequeue(index-1,current.next); // for a single-linked list
}

If the only code you are allowed to write is conditional upon the node argument being null then there is no solution because you can't impact a queue with a non-null head.
If the condition is intended to be current != null then it's possible:
if (current != null) {
if (index > 0)
return recursiveDequeue(index - 1, current.getNext());
}
return current;
This will dequeue index items. Given your no argument method calls it with size - 1 it will dequeue all but the last item.

Related

NullPointerException error when trying to find last item's value in a linked list

I'm still a beginner in Java - I'm trying to create a method that finds the value of the last item in a linked list, and it's throwing a java.lang.NullPointerException error, and it indicates the error is on line 21. From my understanding, a null pointer exception happens when the programmer is calling a reference-type variable to reference basically nothing, since the variable hasn't been declared yet.
For example, if I write Integer k;, I cannot call on k until I declare: k = new Integer(10);. If I write int k;, Java automatically sets the value to 0, since it's a primitive type, and I will be able to call it directly.
In this case, I kind of understand why it's throwing this error, since as you can see in the second line of the getLast() method, I called next, which should be null, since it hasn't been declared yet. However, it's indicating that the error is on line 21, where I reassign last. Why?
How do I fix this code? FYI this is just a practice problem through my school's website, and the task was to complete the getLast() method.
/*
* Class for representing a linked list of ints.
*/
public class List {
public int value;
public List next;
public List(final int setValue) {
value = setValue;
}
/**
* Return the value of the last item in the list.
*/
public int getLast() {
List current = next;
int last = next.value;
while(next != null) {
current = next;
next = current.next;
last = next.value; //ERROR
}
return last;
}
}
You should move the statement that moves to the last node as the last statement of the while loop so that on the next iteration, the loop condition would become false and the loop terminates. In your case, you try to access the next element after you reach the end of the list.
Also, you must use the local variable current for iterating and not assign / change the instance variable next. If you call getLast the next time, it won't work because next now points to null.
Change it as
List current = next;
int last = value;//Set to the current value to begin with
while(current != null) {
last = current.value;
current = current.next;
}
return last;
When the while loop gets to the last node you set next to null with:
next = current.next
You should be able to fix by setting last = current instead of next.
But you should be careful about empty lists. It seems that if you called getLast() on an empty list you'd have a NullPointerException again.
NullPointerException is thrown because next is null and you reference next.value.
You should not change next, use a temporary value to iterate to the end of the list.
public int getLast() {
if (next == null)
return value;
List current = next;
while (current.next != null)
current = current.next;
return current.value;
}

Recursively delete the last occurrence in a linked list, Java

class Link{
private int value;
private Link next;
}
I am asked to write a recursive method to delete last occurrence of a certain value, say 4.
before 2->3->4->5->4->2
after 2->3->4->5->2
The last occurrence only. I know how to delete all occurrence but I can't tell if its the last occurrence. No helper method is allowed.
The one to delete all occurrence
public Link deleteAll(){
if (next == null){
return value==4? null:this;
}else{
if (value == 4){
return next.deleteAll();
}
next = next.deleteAll();
return this;
}
}
You can declare a pointer to the last occurred node and delete that node when reached the last element in list. Following steps explains that -
Declare two pointers one is next as in your above code another can be temp.
Iterate through list using next like you doing in deleteAll method above.
If you find the node you looking for assign that node to temp.In your case 4.
When next is null you reached the end of list now delete, whatever node is in temp delete that node. If temp is still null than no node found in given key.
EDIT:
Possible pseudo Code in case of recursion:
public void deleteLast(Node node,Node temp,Node prev, int data)
{
if(node==null)
{
if(temp!=null && temp.next.next!=null){
temp.next = temp.next.next;}
if(temp.next.next==null)
temp.next = null;
return;
}
if(node.data==data)
{
temp = prev;
}
prev = node;
deleteLast(node.next, temp, prev, int data);
}
Above code should be able to solve your problem. I made some edit in my approach which should be obvious from the code but let me describe it below
I added a prev pointer. Because if we want to delete a particular node we need to assign its next to prev node's next.So, we need the prev node not the node that we want to delete.
I think this change will follow in iterative approach too.
Not really answering your exact question, but as an alternative option, you might consider the following.
Write a recursive method to delete the first occurrence of a specified value, something like this:
public Link deleteFirst(int target) {
if (value == target) {
return next;
}
next = (next == null) ? null : next.deleteFirst(target);
return this;
}
Then you could write a reverse() method as either an iterative or recursive method as you see fit. I haven't included this, but googling should show some useful ideas.
Finally the method to remove the last occurrence of a value from the linked list could then be written like this:
public Link deleteLast(int target) {
return reverse().deleteFirst(target).reverse();
}
Note that as long as your reverse() method is linear complexity, this operation will be linear complexity as well, although constants will be higher than necessary.
The trick is to do the work on the way back -- there is no need for additional parameters, helpers or assumptions at all:
Link deleteLast(int target) {
if (next == null) {
return null;
}
Link deleted = next.deleteLast(target);
if (deleted == null) {
return value == target ? this : null;
}
if (deleted == next) {
next = deleted.next;
}
return deleted;
}

Return the number of elements in a linked list recursively

I have the following recursive method in a class called ImageNode which is passed the head(this - the start of the linked list) from a class called Image.
I thought my code would recursively go through each node, increase the count then when its at the end return the count, unfortunatly not. Where am I going wrong?
private int countRec() {
int count = 1;
ImageNode node = this;
if (node.next != null ){
node = node.next;
count++;
countRec();
}
return count;
}
You're ignoring the result of countRec() - and you're iterating within the recursive call, defeating the purpose. (You're also making a recursive call on the same object, with no parameters and no change in state... so that can't do any good.) My recursive approach would be based on a design of:
If the next node is null, then the size of the list is 1
Otherwise, the size is 1 + the size from the next node onwards.
So:
private int countRec() {
return next == null ? 1 : 1 + next.countRec();
}
Now that doesn't allow for a list of length 0 of course... you probably want to separate the idea of the list from the node, in which case the list class would have something like:
public int count() {
return head == null ? 0 : head.countRec();
}
where the value of head is a reference to the head node if there is one, or null otherwise.
Of course, this will be O(n) in time and space. You can get O(1) space using iteration instead of recursion, and O(1) time by just keeping the size of the list as an instance variable in the list, updating it when you need to. I'm hoping that this question was based on an educational requirement rather than real code though - in production code, you'd just use the collections provided already.
The definition of a recursive function is it is defined in terms of itself: i.e. the count of elements in a list is equal to 0 if an empty list; otherwise it is equal to 1 + the count of the rest of the elements of the list.
The italicized portion of the above definition is where the function call gets made.
private int countRec(ImageNode node) {
if (node == null) {
return 0;
} else {
return 1 + countRec(node);
}
}
A recursive function is useful when it uses the result of the further calls to solve his problem (like an inductive step on mathematics). Your function are not using the return for the countRec() call for anything, and you're still trying to solve the issue without the recursion help. You can solve it by using it, as:
if(node.next != null)
{
node = node.next;
count = countRec()+1;
}
return count;
Of course, since we're telling about getting your code better, you wouldn't even need to use this node var, just doing:
private int countRec() {
if (this.next != null )
return (this.next.countRec())+1;
return 1;
}
Hope that helps.

Unable to understand why count is not getting incremented

As a part of exercise, i am writing a recursive code to count the number of nodes in a queue. The code part which I have added/modified (in NodeQueue.java) is here:
public class NodeQueue implements Queue
{
static protected int count; //for RecNodeCount method only
protected Node beingCountedNode = head; //for RecNodeCount method only
// other methods..
public int RecNodeCount()
{
if(beingCountedNode == null)
return count;
else
{
count++;
beingCountedNode = beingCountedNode.getNext();
return RecNodeCount();
}
}
The entire code is as here:
Queue.java: http://pastebin.com/raw.php?i=Dpkd8ynk
Node.java: http://pastebin.com/raw.php?i=Zy0KbrtJ
NodeQueue.java: http://pastebin.com/raw.php?i=j6hieiLG
SimpleQueue.java: http://pastebin.com/raw.php?i=vaTy41z4
I am unable to understand why I am getting zero even after enqueueing few nodes in the queue. The size variable returns the correct number. I am doing more or less the same with the count variable (I think!) i.e. incrementing the required variable.
Although I believe the method will work (if beingCountedNode is set properly before the call. See #peter.petrov answer), it is weird to use instance variables as parameters for a function. I think the recursive function should have the signature int Count( Node node ) which returns the number of nodes after (including) the given Node.
// returns the number of nodes in the list
public int Count(){ return CountHelper( head ); }
// helper recursive function
// returns the number of nodes in the list after and including "node".
// call with head of the list to get the count of all nodes.
private int CountHelper( Node node )
{
if( node == null )
return 0;
else
return 1 + CountHelper( node.getNext() );
}
Also note in your current example, you never reset count, so if I call RecNodeCount() twice in a row, your method will tell me the count is twice what it actually is. Edit, actually I guess it wouldn't since beingCountedNode would be null, but it is still weird to do it this way.
My guess is this following.
When this line is executed
protected Node beingCountedNode = head;
your head is null.
So beingCountedNode is set to null. Due to this,
later in your method you never enter the else clause.
Just add a few System.out.println calls in RecNodeCount()
and you'll see what exactly is happening in this method.
Maybe this is not a direct answer for your issue, but why do you even use recursive and static variable here? Is' really easy to count nodes with simple while.
public int nodeCount(Node node) {
int result = 0;
while(node != null) {
node = node.getNext();
result++;
}
return result;
}

Anyone know why this method for linked list keeps on going forever?

I have this linked list method that is used to insert before, so it takes a node and puts it before the beforeNode. Currently it does that, but then it goes on forever and makes the linked list infinitely big when it should only be four long. Does anyone see why it keeps on going?
private void insertBefore(Node aNode, Node beforeNode)
{
if(this.getPrevious(beforeNode) != null) {
this.getPrevious(beforeNode).setNext(aNode);
// aNode.setPrevious(beforeNode);
//this.getPrevious(this.getPrevious(beforeNode)).setNext(aNode);
} else {
head = aNode;
}
aNode.setNext(beforeNode);
// beforeNode.setPrevious(aNode);
}
Here is the print list method that could have something to do with it, but I dont think so
public void printList()
{
Node currentNode;
currentNode = this.getHead();
System.out.print("head ->");
while(currentNode!=null)
{
System.out.print(currentNode.getData().toString()+ " -> ");
currentNode = currentNode.getNext();
}
System.out.println("|||");
}
I think some how you are passing the same node for both aNode and beforeNode. In java, every object is a reference. Did you by any chance try to create aNode a copy of beforeNode ? It might have made both the same and causing the linked list to have a self loop. use a copy constructor or things like clone to get a duplicate node.

Categories

Resources