My problem is my delete method isn't deleting the node I want to delete and giving me a infinite loop.
public void delete(String name){
Node current = head;
boolean checker = false;
while(current != null && current.name != name && checker != true){
try{
if(current.name.equals(name)){
Node p = current.previous;
Node q = current.next;
/*The code can somehow get through only above this line, below here its not anymore*/
p.next = q;
q.previous = p;
System.out.println("Item successfully deleted.");
checker = true;
}else if(!current.name.equals(name) && current == tail){
System.out.println("Item not found.");
}
current = current.next;
} catch(NullPointerException e){}
}
}
Im here to asking for a hint or tip about my problem
(Sorry for my bad english)
You are checking if you have reached the end of the list current == tail but not breaking out of it. You can add a break statement inside your else if.
Other than that, you are using == to compare strings. I'm not sure why you added that there and it can be removed. Also, you must (almost always) never catch a NullPointerException.
"infinite loop" means your loop condition is incorrect, you are not making progress in each iteration, or there is a cycle your data. You use both current == null and current == tail to signify that it's the last element. Choice one way. Suggest you rewrite your loop condition to only deal with iteration, and have a conditional with a break if you have a match in the body:
for(current = head; current; current = current.next) {
if(current.name.equals(name)) {
if(current == head)
head = current.next
else
current.previous.next = current.next;
if(current == tail)
tail = current.previous;
else
current.next.previous = current.previous;
break;
}
// if tail.next is not initialized to null
// if(current == tail) break;
}
I see a potential infinite loop with no side effect here. If your list contain a node with node.name set to null then the invocation of current.name.equals(name) results in a NullPointerException. If you are at either end of the list the next or previous pointers will be null which will also result in the same exception. This exception is caught and discarded. Note that this prevents the advance of the current pointer which causes the same iteration to occur. At the very least make sure to print out the exception even if you're not taking any other action. It'll help with debugging.
Your while loop condition is overly complicated. while(current != null) should suffice given that:
Using if(current.name.equals(name)) removes the need for current.name != name. Also, don't use == or != for string comparison. It is a pointer comparison. Most equals methods take care of pointer comparisons.
Use a break or return for flow control here and remove checker boolean. The tail.next should always point to null to signify the end of the list. The only reason I see to have the checker boolean is if delete should remove all matching nodes and you want to know if it happened at least once. From what I see in the code that is not the case.
I would rewrite this as:
public void delete(String name){
Node current = head;
while(current != null){
try{
if(current.name.equals(name)){
...
return;
// Do not advance current here. Refer to finally block below.
}
} catch(NullPointerException e){
e.printStackTrace();
return; // If function should stop on error.
} finally {current = current.next;} // This prevents the repeat as it always happens.
}
System.out.println("Item not found.");
}
Note if you use "break" instead of "return" then the "Item not found." line will always print. You'd have to guard it with an if statement and a flag.
public void delete(String name){
Node current = head;
while(current != null){
if(current.name.equals(name)){
if(current.prev != null){
current.prev.next = current.next
}
if(current.next != null){
current.next.prev = current.prev
}
System.out.println("Removed node")
break;
}
current = current.next;
}
}
You could use this logic to delete the node that matches the name(given name is always present) if node is non null.
Related
I am using a linked list without using collections class for data structure practice.
I wanted to remove an element from the linked list after passing the element value to function
This is the function that i've written.
public boolean remove(String s)
{
if(head.getName().equalsIgnoreCase(s))
{
head = head.getNext();
return true;
}
else
{
Node p =head;
Node current=p.getNext();
while(true) {
if(current == null || current.getName().equals(s)) {
break;
}
p = current;
current = current.getNext();
}
if (current == null)
{
p.setNext(current.getNext());
return true;
}
}
return false;
}
i'm using Node p to store the previous node and current node.
The code falls in the return false section and there is no change in the list.Also i'm getting a null pointer exception warning in the p.setNext(current.getNext()) here.
Please let me know where i'm making mistake.
Regarding the Null Pointer Exception this should ring a bell
if (current == null)
{
p.setNext(current.getNext());
return true;
}
current is null and you are trying to invoke a method from it.
Also it doesn't seem you handle the corner cases like the list is empty or having one element.
current == null
is the not found case. When current == null we should return false, and calling current.getNext() will give the null pointer error. Similarly, the found case is not getting into the block you want. It should suffice, I think, to say if (current != null) where you have if (current == null)
I found https://www.geeksforgeeks.org/linked-list-set-3-deleting-node/ helpful.
Instead of checking true condition based on current value which possibly may or may not be null, you should be having one boolean flag.
This flag value can be made true if you find the passed element.
while(true) {
if(current == null || current.getName().equals(s)) {
flag = true;
break;
}
p = current;
current = current.getNext();
}
if (flag)
{
if(current!=null)
p.setNext(current.getNext());
return true;
}
I am using a binary tree structure here. I am getting a "NullPointerException" from the line containing the while statement. I am completely confused about why that would be.
BinaryTreeNode<CharData> currNode = theTree.findValue(data);
// Move up the Binary Tree to create code.
while(currNode.getParent() != null) {
// The loop does some stuff that doesn't
// affect what is assigned to currNode.
// Move to the parent node for the next iteration.
currNode = currNode.getParent();
} // End the while loop.
return code; // Return the string of binary code.
Find value is a method from my BinaryTree class that searches for and finds the node containing specific data. I know this works from testing it separately outside of this implementation.
The only reason why the while-loop statement can throw a NPE is, when currNode is null. I suspect findValue() returned null.
I guess one fix (when you care about the topmost node) would be:
while(currentNode != null) {
rootNode = currentNode;
currentNode = currentNode.getParent();
}
Or the typical pattern which relies on boolean shortcut evaluation:
while(curentNode != null && currentNode.getParent() != null)
Or my prefered solution using guards:
if (currentNode == null)
throw NotFound(); // or return something
while(curentNode.getParent() != null) {
If you see the code:
BinaryTreeNode<CharData> currNode = theTree.findValue(data);
I guess, currNode is getting some value if findValue() able to search data else it is returning NULL values.
When it returns a NULL value it will throw NPE.
To avoid it, you can modify your code a little bit.
while(currNode != null && currNode.getParent != null) {
// your code here
}
I need to make a method that removes the last element of a LinkedList using recursion.
This is what I have so far but it doesn't seem to be removing the node...when i call list.size() it is still the same size with the same values. What am I doing wrong here?
This is for Java by the way
public void removeLastElement(Node curr){
if (curr == null)
return;
else{
if(curr.next == null)
curr = null;
else
removeLastElement(curr.next);
}
}
In a LinkedList to remove the last element you have to get the penultimate element and set
curr.next = null
You're in the right way to get the recurrent function to remove the last node. The problem is you're identifying the penultimate node with curr.next == null, if you got it, you nullify it, but that's your actual input! So, you must check if the actual node is the antepenultimate node on the list:
if (curr.next.next == null) {
curr.next = null; //Now you're modifying the data in your input.
}
With this change, there are more basic cases to check, but that's up to you, my friend.
Boolean deleteLast(Node n)
{
if(n.next == null)
return true;
if(deleteLast(n.next))
{
n.next = null;
return false;
}
return false;
}
Node deleteLast(Node n) {
if (n.next == null)
return null;
n.next = deleteLast(n.next);
return this;
}
The general idea is you ask the next node "hey, can you tell me where you are, and delete your last node?" The last node can then just say "I'm nowhere" and it'll all fall into place.
This is very similar to Aadi's answer, just using Nodes instead of booleans.
I am trying to make an add method for a linked list, but for some reason (that is not obvious to me, in fact I came here to get help finding the error) it goes into an infinite loop every time.
EDIT: I found the error, and I will keep my original code with a comment with the corrected code
public void insert(String majorName)
{
MajorNode newNode = new MajorNode(majorName, 1);
boolean inList = false;
MajorNode current = first;
if(isEmpty())
{
first = newNode;
// inList = true;
}
else
{
while(current.next != null)
{
if(current.majorName.equalsIgnoreCase(majorName))
{
current.frequency++;
inList = true;
break;
}
else
{
current = current.next;
}
}
}
if(!inList)
{
newNode.next = first;
first = newNode;
}
}
Here is my node class if it is needed:
public class MajorNode
{
public String majorName;
public int frequency;
public MajorNode next;
public MajorNode(String majorName, int frequency)
{
this.majorName = majorName;
this.frequency = frequency;
}
public String toString()
{
return majorName + " " + frequency;
}
}
On the first call to insert(), one assumes isEmpty() returns true and consequently first is set to the newNode before newNode's next field is set to the previous (null) value of first. Thus, when the list is non-empty, the loop iterates indefinitely on the last element in the list whose next field points to itself.
Out of curiosity, why are you trying to implement your own linked list functionality rather than build upon available packages (such as java.util.LinkedList<E>)?
When you create the first node you do this:
if(!inList)
{
newNode.next = first;
first = newNode;
}
This points the first nodes next at itself... hence a loop
You should be leaving the newNode.next as null for the first node, so that when you insert the second item, you reach the end of the chain..
You will have an wrong frequency if you add a node which is similar to the last node of your List. Consider this situation (adding 2 similar nodes in the empty list)
You will add a node1 in a blank list. So first & current will point to node1. (but node1.next will be null)
If you add the same node (or a node with a same majorName), you will reach to while loop (because List is not empty now). And also, you will not enter into a while loop as well. (as your current.next is still null)
and you will end up with two noes with same majorName in your list.
I would suggest to use
while(current != null)
instead of
while(current.next != null)
What is a doubly linked list's remove method?
The same algorithm that Bill the Lizard said, but in a graphical way :-)
(source: jaffasoft.co.uk)
The general algorithm is as follows:
Find the node to remove.
node.previous.next = node.next
node.next.previous = node.previous
node.previous = null
node.next = null
Dispose of node if you're in a non-GC environment
You have to check the previous and next nodes for null to see if you're removing the head or the tail, but those are the easy cases.
public void remove ()
{
if (getPreviousNode () != null)
getPreviousNode ().setNextNode (getNextNode ());
if (getNextNode () != null)
getNextNode ().setPreviousNode (getPreviousNode ());
}
Doubly Linked List Implementation Remove Methods (from my second programming assignment):
public void remove(int index) {
if(index<0 || index>size())
throw new IndexOutOfBoundsException("Index out of bounds. Can't remove a node. No node exists at the specified index");
if(size()==0) {
throw new NullPointerException("Empty list");
}
if(!isEmpty()) {
Node current;
//starting next one to our head
current = head.next;
for(int i=0;i<index;i++) {
current = current.next;
}
current.previous.next = current.next;
current.next.previous = current.previous;
numOfNodes--;
sizeChangeCount++;
}
}
public boolean remove(T o) {
Node current = head;
for(int i=0;i<size();i++) {
current=current.next;
if(current.data.equals(o)) {
current.previous.next = current.next;
current.next.previous = current.previous;
numOfNodes--;
sizeChangeCount++;
return true;
}
}
return false;
}
Are you asking for the name of a method in the api? That answer would simply be remove, assuming you are asking about java.util.LinkedList which is in fact a double linked list.
...or are you asking about what the name of the algorithm to remove an element from that type of data structure is called? Well.. the answer for that would also be to remove an element. Now for the actual algorithm to do it... it's really just a matter of changing the next pointer in the previous node and the last pointer in the next node. However, if you are using your data structure from multiple threads, you will need to either synchronize the remove method, or do the removal steps in an order that will make sense for your usage pattern for the data structure.
What about the current pointer pointer? You have to move crnt to the next node.
http://pastebin.ca/1249635