Node class
private class Node<E> {
E data;
Node<E> next;
public Node(E obj) {
data = obj;
next = null;
}
}
insert method (ascending order)
public void insert(E obj) {
Node<E> newNode = new Node<E>(obj);
Node<E> prev = null, curr = head;
while(curr != null && ((Comparable<E>)obj).compareTo(curr.data) >= 0) {
prev = curr;
curr = curr.next;
}
if(prev == null)
head = newNode;
else {
prev.next = newNode;
newNode.next = curr;
}
currentSize++;
}
remove method
public E remove() {
if(isEmpty())
return null;
E tmp = head.data;
head = head.next;
currentSize--;
return tmp;
}
I get Null Pointer Exception at the line
E tmp = head.data;
in the remove method
The error is fixed if the change the else statement in my insert method to
else
prev.next = newNode;
newNode.next = curr;
There's a problem when you insert a new node that needs to go at the beginning of the list (because it's smaller than the current head node). When you get to this part:
if(prev == null)
head = newNode;
you're setting head to be the new node you've just created, but you also need to set newNode.next to be the previous head. So you really want
if(prev == null) {
newNode.next = head;
head = newNode;
}
which inserts the new node at the beginning but tacks the previous head onto it.
With your code as it stands, when you add a second element that should go at the beginning, you're accidentally discarding the element that's already there, but you're still increasing currentSize; so you end up with a list with only one element, but a currentSize of 2. When you then try to remove two elements, the second one fails with a NullPointerException because you try to read the data inside a non-existent element.
Related
I have a sorted doubly linked list in which the first and last elements are null. This means when I insert the values a, b, c. The result should look as follows: {null, a, b, c, null}
The empty sorted doubly linked list should look like this: {null, null} in which the first and last elements are always are null.
The problem is that when I insert data in the sorted doubly linked list, the data is not sorted correctly and the 2 null values are always at the end of the list. How can I fix this?
Here is my current insert method:
public void addElement(String element) {
// new node which will be inserted in the list
Node newNode = new Node();
newNode.data = element;
// if the list is empty
if (size == 0) {
last = newNode;
newNode.next = first;
first = newNode;
size++;
} else {
Node current = first;
// if the element should be at the beginning of the list
if (current.data.compareTo(element) > 0) {
newNode.next = current;
newNode.previous = null;
current.previous = newNode;
first = newNode;
} else {
while (current != null) {
if (current.data.compareTo(element) <= 0) {
if (current.next == null) {
newNode.next = current.next;
newNode.previous = current;
current.next = newNode;
break;
}
newNode.next = current.next;
newNode.previous = current;
current.next.previous = newNode;
current.next = newNode;
break;
} else {
current = current.next;
}
}
}
size++;
}
}
It is not so clear what you are doing in your code, so I modified it a bit and made more OO style, so here it is:
class Node {
String data;
Node next, previous;
}
public class SortedDLL {
private Node first;
private Node last;
private int size = 0;
public SortedDLL() {
size = 0;
first = new Node();
last = new Node();
first.next = last;
last.previous = first;
}
public void addElement(String element) {
Node newNode = new Node();
newNode.data = element;
if (size == 0) {
first.next = newNode;
newNode.previous = first;
newNode.next = last;
last.previous = newNode;
} else {
Node node = first;
while (node.next.data != null && node.next.data.compareTo(newNode.data) < 0) {
node = node.next;
}
newNode.next = node.next;
node.next.previous = newNode;
node.next = newNode;
newNode.previous = node;
}
size++;
}
public void print() {
Node node = first;
while (node != null) {
System.out.print(node.data != null ? node.data + " " : "null ");
node = node.next;
}
}
public void printReverse() {
Node node = last;
while (node != null) {
System.out.print(node.data != null ? node.data + " " : "null ");
node = node.previous;
}
}
public static void main(String[] args) {
SortedDLL sortedDLL = new SortedDLL();
sortedDLL.addElement("c");
sortedDLL.addElement("a");
sortedDLL.addElement("b");
sortedDLL.addElement("c");
System.out.println("list: ");
sortedDLL.print();
System.out.println("\nlist reverse: ");
sortedDLL.printReverse();
}
Output:
list:
null a b c c null
list reverse:
null c c b a null
the problem starts at the first call when size == 0
you push the first null to the end.. and the first node becomes the new node.
then, if you fix this you will get null pointer exception at the row :
if (current.data.compareTo(element) > 0) {
because the current will be null and the will not have data.
you should ignore the first null in the first insert and every insert after that.
Depending on implementation I think you're just doing the right thing in the wrong place.
while (current != null) {
if (current.next == null) {
newNode.next = null;
newNode.previous = current;
current.next = newNode;
break;
}
if (current.next.data.compareTo(element) > 0) {
newNode.next = current.next;
newNode.previous = current;
current.next.previous = newNode;
current.next = newNode;
break;
} else {
current = current.next;
}
}
Instead of checking if the currently selected node is smaller you need to check if the node after is bigger because then you can place the node.
And checking if current.next is null needs to be done outside of that comparison.
This method will create a new Node object and insert it in order by the 3rd value in the CSV(i.e. KYZ98765, ABC12345, etc.) it works except for the last node insert...
Here is my code:
void sortedInsert(Node new_node)
{
Node current;
/* Locate the correct node before inserting. */
//System.out.println(current.data);
if(head.next == null)
{
new_node.next = head;
head = new_node;
System.out.println("Inserted head: \n" + head.data.toString());
}else
{
current = head;
while (current.data.getbLnum().compareTo(new_node.data.getbLnum())>=0)
{
System.out.println("here again");
current = current.next;
}
new_node.next = current.next;
current.next = new_node;
System.out.println("Inserted: \n" + current.next.data.toString());
}
}
Here is the output:
FundManagerLicense FundManagerLastname FundManagerFirstname
ABC12345 Wonch Bob
FundManagerLicense FundManagerLastname FundManagerFirstname
ZYK98765 Ferguson Jesus
FundManagerLicense FundManagerLastname FundManagerFirstname
GYZ98765 Ferguson Jose
FundManagerLicense FundManagerLastname FundManagerFirstname
KYZ98765 Ferguson Jimmi
This is my input in the order each element is fed to the sortedInsert:
BROKER,ADD,KYZ98765,Jimmi,Ferguson,321-131,0.02
BROKER,ADD,ABC12345,Bob,Wonch,321-112,0.1
BROKER,ADD,GYZ98765,Jose,Ferguson,321-111,0.02
BROKER,ADD,ZYK98765,Jesus,Ferguson,321-141,0.02
Can anyone see what is going wrong?
Try it this way.
private int compare(Node n1, Node n2) {
return n1.data.getbLnum().compareTo(n2.data.getbLnum());
}
void sortedInsert(Node newNode) {
Node prev = null;
Node next = head;
while (next != null &&
compare(newNode, next) >= 0) {
prev = next;
next = next.next;
}
if (prev == null) head = newNode;
else prev.next = newNode;
newNode.next = next;
}
It should be fairly self-explanatory, go through the list, keeping track of the nodes that will come before (prev) and after (next) the inserted node, until next is null, or until newNode cannot come after next. Then insert the new node and, if necessary, make it the head.
You have a big risk of a null pointer exception.
while (current.data.getbLnum().compareTo(new_node.data.getbLnum())>=0)
{
System.out.println("here again");
current = current.next;
}
When you reach the end of your list current will become null and the next call to current.data will throw and exception.
Do you know why is not being thrown? Because you made your list a circular list!
new_node.next = head;
head = new_node;
The new node is the head and point to itself as next. So your last insertion goes all the way to the end f the list, fails to find an insertion place (because your last input should be placed at the end of the list) and then became the next after the head.
To solve the problem you need two changes:
void sortedInsert(Node new_node){
Node current;
/* Locate the correct node before inserting. */
//System.out.println(current.data);
if(head.next == null)
{
new_node.next = **null**;
head = new_node;
System.out.println("Inserted head: \n" + head.data.toString());
}else
{
current = head;
while (current.data.getbLnum().compareTo(new_node.data.getbLnum())>=0 **&& current.next != null**)
{
System.out.println("here again");
current = current.next;
}
new_node.next = current.next;
current.next = new_node;
System.out.println("Inserted: \n" + current.next.data.toString());
}
}
Test them and let me know.
I solved the next exercises having two solutions: https://www.hackerrank.com/challenges/reverse-a-doubly-linked-list
First (non-recursive):
/*
Insert Node at the end of a linked list
head pointer input could be NULL as well for empty list
Node is defined as
class Node {
int data;
Node next;
Node prev;
}
*/
Node Reverse(Node head) {
if (head == null) return null;
Node current = head;
while (current.next != null) {
Node temp = current.next;
current.next = current.prev;
current.prev = temp;
current = temp;
}
current.next = current.prev;
current.prev = null;
return current;
}
Second algorithm (recursive):
/*
Insert Node at the end of a linked list
head pointer input could be NULL as well for empty list
Node is defined as
class Node {
int data;
Node next;
Node prev;
}
*/
Node Reverse(Node head) {
if (head.next == null) {
head.next = head.prev;
head.prev = null;
return head;
}
Node newHead = Reverse(head.next);
Node temp = head.next;
head.next = head.prev;
head.prev = temp;
return newHead;
}
According to the book, the solution must be O(n). I guess using recursive solution is more elegant but maybe I'm wrong. Can you help to determine the space and time complexity of these two algoritms, or in your, which is better in performance?
The question is a bit unclear, both solutions seem to be O(n) in both time and space. Although you could probably remove the special cases and make Torvalds happy. Something like:
Node Reverse(Node head) {
if (head == null) return null;
Node current = head;
while (current != null) {
Node temp = current.next;
current.next = current.prev;
current.prev = temp;
current = temp;
}
return current;
}
Node Reverse(Node head) {
Node temp = head.next;
head.next = head.prev;
head.prev = temp;
return temp==null?head:Reverse(temp);
}
I have not tested these, use them as inspiration only. (Also the recursive will nullpointer if head is null in the beginning).
I am attempting to solve a problem on hackerrank. The question to solve is
"You’re given the pointer to the head node of a sorted doubly linked list and an integer to insert into the list. Create a node and insert it into the appropriate position in the list. The head node might be NULL to indicate that the list is empty."
The Node class they provide is defined as
/*
Insert Node at the end of a linked list
head pointer input could be NULL as well for empty list
Node is defined as
class Node {
int data;
Node next;
Node prev;
}
*/
My attempted solution is
Node SortedInsert(Node head,int data)
{
// new node to insert into linked list
Node newNode = new Node();
newNode.data = data;
if (head == null)
{
return newNode;
}
else
{
// start at beginning of list
Node cur = head;
// traverse through sorted list
while (cur != null && cur.next != null)
{
if (data < cur.next.data)
{
newNode.next = cur.next;
newNode.prev = cur;
cur.next.prev = newNode;
cur.next = newNode;
return head;
}
else
{
cur = cur.next;
}
}
return head;
}
}
I am not quite sure what is wrong here, but hackerrank is saying my solution is incorrect. Any idea as to what could be going wrong?
Let's assume our DLL is 1=2=3=4=5
Now consider the case : add 6 to DLL
The loop does not cover the corner cases.
while (cur != null && cur.next != null)
{
if (data < cur.next.data)
{
newNode.next = cur.next;
newNode.prev = cur;
cur.next.prev = newNode;
cur.next = newNode;
return head;
}
else
{
cur = cur.next;
}
}
Modification :
if(data < cur.data) {
newNode.next = cur;
newNode.prev = null;
cur.prev = newNode;
head = newNode;
return head;
}
while (cur != null)
{
if (data >= cur.data)
{
if(cur.next == null) {
newNode.next = cur.next;
newNode.prev = cur;
cur.next = newNode;
return head;
}
newNode.next = cur.next;
newNode.prev = cur;
cur.next.prev = newNode;
cur.next = newNode;
return head;
}
else
{
cur = cur.next;
}
}
I realize this should be a very easy method to implement and I have no idea why this code is not working.
I get a NullPointerException at tail.next = node. If it is not commented out, it does not pass the tester.
public void addBack (int x)
{
IntegerNode node = new IntegerNode(x,null);
if (head == null)
head = node;
else{
node.prev = tail;
//tail.next = node;
tail = node;
}
count++;
}
When the list is empty, set your head and tail to the new element. Should be ok after that, though more null checks are rarely a bad idea.
if (head == null) {
head = node;
tail = node;
} else {
node.prev = tail;
tail.next = null; // Did you really mean tail.next = node? This looks more likely..
tail = node;
}