Deleting nodes of Singly Linked List in Java - java

I'm having a problem deleting nodes from singly linked lists in Java. I have a list, which has data of integers, and I need to delete all nodes, whose value can be divided by divided by four. I also need to move the head and tail pointers in case either of the head or tail elements are deleted. I wrote method for this, and most of the time it works just like I need it to, but sometimes it throws NullPointerException. How can I fix it? Here's my code:
public void delete(){
Node temp = head, prev = null;
if (temp != null && temp.data % 4 == 0)
{
head = temp.next;
temp = head;
}
while (temp.next != null)
{
if (temp.data % 4 != 0) {
prev = temp;
temp = temp.next;
}
else {
prev.next = temp.next;
temp = prev.next;
}
}
if (tail.data % 4 == 0) {
tail = prev;
tail.next = null;
}
}

while (temp.next != null): temp may be null. And some more small problems.
This is due to too much complexity.
public void delete() {
Node prev = null;
for (Node temp = head; temp != null; temp = temp.next) {
if (temp.data % 4 == 0) {
if (prev == null) {
head = temp.next;
} else {
prev.next = temp.next;
}
} else {
prev = temp;
}
}
tail = prev;
}
The above sets prev to the valid previous node.
The deletion considers deletion from head or from prev.next.
The tail is updated to the last element.

in your while condition add one more null check:
while (null != temp && null != temp.next)

Related

How to insert a node after another node using doubly linked list?

I want to insert a node after another node in a doubly-linked list but when I provide such a key that doesn't exist in the Linked list then this method gives me an error. How should I fix this error? here is my code. Thanks in Advance.
{
public void AddAfter(int insertAfter, int data)
{
DLNode n = new DLNode(data);
DLNode curr = head;
if(head == null)
head = n;
else
{
while(curr.Data != insertAfter && curr != null)
{
curr = curr.next;
}
if(curr != null)
{
n.next = curr.next;
n.prev = curr;
n.next.prev = n;
curr.next = n;
NumNodes++;
}
else
System.out.println("The Key "+insertAfter+" doesn't exist: ");
}
}
}
... but when I provide such a key that doesn't exist in the Linked list then this method gives me an error.
The problem occur in your while loop condition (e.g., curr.Data != insertAfter && curr != null). Here, you are first accessing the data field of the curr variable and then checking whether curr is null or not.
How should I fix this error?
You need to do it in reverse order. The following code should solve your problem.
public void AddAfter(int insertAfter, int data) {
DLNode n = new DLNode(data);
DLNode curr = head;
if(head == null) {
head = n;
}
else {
while(curr != null && curr.Data != insertAfter) {
curr = curr.next;
}
if(curr != null) {
n.next = curr.next;
n.prev = curr;
n.next.prev = n;
curr.next = n;
NumNodes++;
}
else {
System.out.println("The Key "+insertAfter+" doesn't exist: ");
}
}
}

Creating a sorted link list out of a normal linked list

As I've just started programming a few months back a lot of new information is coming and I'm having trouble catching up.So here I have created what I thought was a sorted linked list.Turns out it is not sorted
public boolean insert(Person person) {
Node n = new Node(person);
Node p = head;
if(p == null) {
head = n;
size++;
return true;
} else {
Node temp = p;
int comparison;
while(temp.next != null) {
comparison = temp.person.name.compareTo(person.name);
if(comparison == 0){
return false;
}
temp = temp.next;
}
temp.next = n;
size++;
return true;
}
}
The method works,it inserts the persons,but they arent sorted like they should be.What part of the code do I need to change/remove in order to make it sort.
Thanks!
You should insert like this:
static boolean insert(Person person) {
Node newNode = new Node(person);
if (head == null) {
head = newNode;
size++;
return true;
}
Node current = head;
Node prev = null;
int comparison;
while (current != null) {
comparison = person.name.compareTo(current.person.name);
if (comparison == 0) {
return false;
} else if (comparison > 0) { /// greater than
if (current.next == null) { // check if reach tail of the linked list add and break
current.next = newNode;
break;
}
} else { // less then
if (prev == null) { // check if it should be first then put and break
Node oldHead = head;
head = newNode;
head.next = oldHead;
break;
}
prev.next = newNode;
newNode.next = current;
break;
}
prev = current;
current = current.next;
}
size++;
return true;
}
There is a problem in your else part. You are returning false when same value is given. But it is not interpreted properly for a valid case.
You need to have as below.
Check current node value - Check for null pointer exception
Check next node value - Check for null pointer exception
If current input is between currentNode and nextNode then do insert between.
If reaches last node, then insert at the end

Remove Duplicates from Linked List

So I have a linked list that I am trying to remove duplicates from.
My basic algorithm that I thought up is to pretty much use the runner technique. Where I keep two pointers to compare adjacent elements. If they are the same I change the pointer of p1 to point to p1.next.next if not I keep traversing the list. However I keep getting a null pointer exception in the solution I have typed.
Node RemoveDuplicates(Node head) {
// This is a "method-only" submission.
// You only need to complete this method.
if (head == null){
return null;
}
Node current = head;
Node runner = head;
while(current != null && runner != null && runner.next != null){
runner = runner.next;
if(runner.data == current.data){
if(current.next != null){
current = current.next.next;
}
}else{
current = current.next;
}
}
return current;
}
At the point that I exit the while loop current is null. Which I think is the problem. How would I return the head of the altered list.
OK, although you've already accepted an answer, here's some example code using recursion to remove the dups from an ordered list per your request in the comments. (if your list isn't ordered, order it :) )
public Node removeDups(Node root) {
if (root.next == null)
return root;
root.next = removeDups(root.next);
if (root.data == root.next.data)
return root.next;
return root;
} // call as root = removeDups(root);
As you mentioned, recursion isn't really necessary here but you're using a Node-based linked list which is recursively defined. So, when it makes sense, the elegance of the solution has its benefits.
What I like about it is that you're not doing any node.next.next or needing to check for that null case. Once the stack starts unwinding, you're already in a position to start checking for dups. Then it's just a matter of comparing root.data and root.next.data; both of which you already know exist.
You can do this with single traversal with 2 pointer.and also this code works with single while loop.
public Node deleteDuplicates(Node head) {
Node current=head;
if (head == null)
return null;
else
{
Node runner=head.next;
while(head.next!=null && runner!=null)
{
if(head.val == runner.val)
prev=runner.next;
else
{
head.next=runner;
head=head.next;
prev=runner.next;
}
}
head.next=runner;
}
return current;
}
First of all, you'll want to return head at the end, so that you are returning the list, not just the last element.
Second thing, you'll want to modify the .next references instead of assigning them in some of the cases.
Note this doesn't work if the list isn't sorted.
Before: 1 1 3 3
After: 1 3
This code works (and I've tested it)
static Node RemoveDuplicates(Node head) {
if (head == null) return null;
Node current = head;
Node runner = head;
while (current != null && current.next != null) {
runner = current.next;
while (runner != null && runner.data == current.data) {
current.next = runner.next; // skip the repeat
runner = runner.next;
}
current = current.next;
}
return head;
}
You can do this in a single traversal. Just maintain two pointers temp
and next_of_next. Make temp iterate for each node and when the data of temp and the next node is equal, point next_of_next to the alternate node after temp and delete the node after temp.
Node removeDuplicates(Node head)
{
Node temp = head;
Node next_of_next;
if (head == null)
return;
while (temp.next != null)
{
if (temp.data == temp.next.data)
{
next_of_next = temp.next.next;
temp.next = null;
temp.next = next_of_next;
}
else
temp = temp.next;
}
return head ;
}
Here an apporach without recursion using a HashSet:
public void RemoveDuplicates()
{
if (head != null)
{
var hm = new HashSet<T>();
Node current = head;
Node prev = null;
while (current != null)
{
if (!hm.Contains(current.Value))
{
hm.Add(current.Value);
prev = current;
current = current.Next;
}
else
{
prev.Next = current.Next;
current = prev.Next;
}
}
}
return head;
}

Why doesn't this merge-sort function cause an infinite loop?

I'm working on a project that requires me to implement merge-sort on a linked list and I am using the code from this post Here to help me. Can someone explain to why on line 6, when I call return merge(merge_sort(head),merge_sort(sHalf)); the method merge_sort(head) inside of it, which contains the same head pointer doesn't cause an infinite loop? It seems to me that it is starting all over again with the same head pointer.
public Node merge_sort(Node head) {
if(head == null || head.next == null) { return head; }
Node middle = getMiddle(head); //get the middle of the list
Node sHalf = middle.next; middle.next = null; //split the list into two halfs
return merge(merge_sort(head),merge_sort(sHalf)); //recurse on that
}
//Merge subroutine to merge two sorted lists
public Node merge(Node a, Node b) {
Node dummyHead, curr; dummyHead = new Node(); curr = dummyHead;
while(a !=null && b!= null) {
if(a.info <= b.info) { curr.next = a; a = a.next; }
else { curr.next = b; b = b.next; }
curr = curr.next;
}
curr.next = (a == null) ? b : a;
return dummyHead.next;
}
//Finding the middle element of the list for splitting
public Node getMiddle(Node head) {
if(head == null) { return head; }
Node slow, fast; slow = fast = head;
while(fast.next != null && fast.next.next != null) {
slow = slow.next; fast = fast.next.next;
}
return slow;
}
It's because of the previous line:
Node sHalf = middle.next; middle.next = null;
Specifically, the middle.next = null; part.
Understand that even though the head pointer is the same, we are splitting the list into half, using middle.next = null. So, in the next recursive call, it's only half the linked list which was sent originally.
And at one point, it will reach head.next == null condition.

Remove the node that contains the key from the Linked list

I have a remove method , find the element in that list and delete it.That topic is about Doubly linked list.Is my operation true in if and else if statement for the formation of the new list?
public void Remove(int key) {//key = number in the list.
if (head == null) {
System.out.println("Empty List..!");
} else if (key == head.key) {
head.prev.next = head.next;
head.next = null;
noOfNodes--;
} else if (key == tail.key) {
tail.next.prev = tail.prev;
tail.prev = null;
noOfNodes--;
} else {
for (LinkedListNode temp = head; temp.next != null; temp = temp.next) {
if (temp.key == key) {
temp.prev.next = temp.next;
temp.next.prev = temp.prev;
temp.prev = null;
temp.next = null;
noOfNodes--;
}
}
}
}
From your code, it looks like tail is the last node of your linked list.
So, this might be the issue tail.next.prev = tail.prev;. Since tail.next is null as tail is the last element, when you access prev on tail.next it throws NullPointerException.

Categories