I can't add a node into an empty list - java

I stumbled upon a weird problem with adding two linked lists into a third one in Java, the first linked list "myList1", the second linked list "myList2" and the third one "myList3".
The combining method is supposed to to add the first LinkedList "myList1" then the second "myList2" into the third LinkedList "myList3", but I faced a problem with adding them to third list while it's empty, but if the third list has at least one element every thing goes smoothly.
The code:
Node current = myList1.head;
while (current != null) {
Node newcurrent = myList3.head;
int h1 = current.getData();
Node newNode = new Node(h1);
if (newcurrent == null)
//the problem is with this code
newcurrent = newNode;
else {
if (newcurrent.getLink() == null) {
newNode.setLink(newcurrent.getLink());
newcurrent.setLink(newNode);
} else {
Node current11 = newcurrent;
while (current11.getLink() != null) {
current11 = current11.getLink();
}
current11.setLink(newNode);
}
}
current = current.getLink();
}
The node is not added to the third LinkedList if the third list is empty, and I tried many other codes but it didn't work either, but if I entered at least one element to the third LinkedList the list is added normally.
other codes I tried :
newcurrent.setLink(newNode);
and
newNode = newcurrent;
newcurrent = newNode;
and
newNode.setLink(newcurrent);
newcurrent.setLink(newNode);
and
newNode.link = newcurrent;
newcurrent.link = newNode;

You're overcomplicating this a bit, I think. The links within the list are already there. You only need to link myList3.tail to myList1.head, no need to loop through adding each node independently. Since you don't look like you are storing a tail, you'll need to iterate to the end of myList3 to find it.
if (myList3.head == null)
myList3.head = myList1.head;
else {
Node list3iter = myList3.head;
while (list3iter.getLink() != null) {
list3iter = list3iter.getLink();
}
list3iter.setLink(myList1.head);
}
}
One further note, I find it painful to try to keep track of names like current, current11, newcurrent, etc. They all mean just about the same thing to my brain. If you're like me, a bit more descriptive naming might help you keep track of what your variables are meant to be doing here.

Node newcurrent = myList3.head;
....
if (newcurrent == null)
//the problem is with this code
newcurrent = newNode;
Not sure why you have two lists, but the last line above is just assigning to local variable. Should it be as follows instead?
myList3.head = newNode

Related

Reversing a singly linked list [Java]

I was wondering if someone could help explain how to reverse a singly linked list without creating new nodes or changing data in the existing nodes. I am trying to study for finals and we had this question on a previous test. They don't release answers to the coding portions of the test and I haven't been able to figure it out.
They told us the best way to reverse it was by using a "runner technique" which I believe I understand what that is. They described it as using two pointers or counters to run through a list and gather information but I'm not sure how to use that to reverse a singly liked list. I was able to brute-force code to reverse a list of length 2, 3, and 4 but I was unable to make a loop or do it recursively. Any code or an explanation on how to go about this would be appreciated, thank you.
You can derive the code by starting with the idea of merely - one by one - popping elements off the input list and pushing them onto an initially empty result list:
NODE reverse(NODE list) {
NODE result = null;
while (list != null) {
NODE head = <pop the first node off list>
<push head onto result>
}
return result;
}
The result will be the reverse of the input. Now substitute Java for the missing pieces
NODE reverse(NODE list) {
NODE result = null;
while (list != null) {
// pop
NODE head = list;
list = list.next;
// push
head.next = result;
result = head;
}
return result;
}
And you're done...
It depends on your implementation of the list, but I would recurse to the end and then reverse the references.
void Reverse(List pList) {
Reverse(pList, null, pList.First); // initial call
}
void Reverse(List pList, Node pPrevious, Node pCurrent) {
if (pCurrent != null)
Reverse(pList, pCurrent, pCurrent.Next); // advance to the end
else { // once we get to the end, make the last element the first element
pList.First = pPrevious;
return;
}
pCurrent.Next = pPrevious; // reverse the references on all nodes
}

Removing duplicate element from a linked list- Java

EDIT
I decided to use a HashSet instead as it has is O(N). However, I am still having an issue that it's not deleting all repeating numbers, 10 13 11 11 12 11 10 12 11.
It returns : 10 13 11 12 10 11
static void removeDups(Node node) {
HashSet<Integer> values = new HashSet<Integer>();
Node previous = null;
while(node != null) {
if(values.contains(node.data))
previous.next = node.next;
else
values.add(node.data);
previous = node;
node= node.next;
}
}
Irrelevant
I am trying to remove duplicate elements from a linked list but for some reason, It does not remove the last repeating element. For instance if the list is 10,11,12,11,12,9,11, It returns : 10,11,12,9,11.
public static void removeDups1(Node head){
if(head == head.next)
head = head.next.next;
Node fastptr =head;
Node slowptr = head;
while(slowptr.next != null && fastptr.next.next !=null) {
if(slowptr.data == fastptr.data) {
fastptr.next = fastptr.next.next;}
slowptr = slowptr.next;
fastptr = fastptr.next;
}}
Checking fastptr.next.next == null prematurely exits your loop.
Your algorithm is trying to find if there are any duplicates for each element from the current position to the next two positions in the linked list. But duplicates can occur anywhere in the linked list. Therefore, for each element, it should traverse through the linked list once again.
That would be a O(n^2) solution
A better approach would be to maintain a hash to keep track of already visited data.
This would be a O(n) solution.
I think, since at the beginning you are pointing both fastptr and slowptr to the same Node, and always end up pointing them to the same node at the end of the while, you're always comparing the same Nodes here, doing nothing valuable to the algorithm:
if(slowptr.data == fastptr.data)
Anyways, the algorightm's logic seems all wrong.
Like others sayd, you should do two loops, one inside another: the first one to the slowptr, the second one to the fastptr
Try to implement based on this proposition:
For all Node (pointed by slowptr, first loop), for all subsequent nodes (second loop) do see if they are the same.
I don't see real Java when I look to your code. But anyway as #Aishwarya said a better solution is to build a map or hash set for better performance. Using Java built-in functions it is even simpler. Just do:
LinkedList<Node> yourList = ...
LinkedList<Node> filteredList = new LinkedList<>(new HashSet<Node>(yourList));
To make this work properly you must make sure that Node equals(Object o) and hashCode()are correctly implemented.
Then your (generic) duplicate removal function might be:
public static void removeDups(LinkedList pList) {
return new LinkedList(new HashSet(pList));
// indeed specifying <Node> is not really needed
}

Questions about traversing, inserting, and deleting nodes

Just started learning nodes and I have a few questions. Let's say I have a node class that looks like this:
private E number;
private Node next;
/**
* Constructor
*/
Node(E e){
number = e;
next = null;
}
and I have a series of linked nodes with the starting node named first like so:
first->(1)->(2)->(3)->(5)->(6)
Assuming the list is not empty, to traverse the list, I would do something like so:
Node curr = first;
while(curr != null){
System.out.print(curr);
curr = curr.next;
}
I understand that you cannot traverse a link list like this backwards, so does this mean that whenever I call curr.next the previous elements are just lost?
I was also wondering if first, my original list, will ever be affected by a temporary node list like curr? For example, if I was to insert or delete a node on the list with codes similar to these:
Insert:
Node curr = first;
Node newNode = new Node(4);
while(curr != null){
if(curr.number == 3){
newNode.next = curr.next;
curr.next = newNode;
}
curr = curr.next;
}
Delete:
Node curr = first;
Node parent = first;
while(curr != null){
if(curr.number == 3){
parent.next = curr.next;
}
parent = curr;
curr = curr.next;
}
Would the above code modify first or would I have to set first = curr; after the insertion or deletion for the changes take place? If they do modify first, how come curr = curr.next; doesn't modify first? What if I wanted to return the deleted node? Would I just do something like curr.next = null; and then return curr;?
does this mean that whenever I call curr.next the previous elements are just lost?
As you traversed down the list, you never modified first and you never modified the next link of any Node. So no node is ever really lost. Previously visited nodes just become a bit less convenient to access because you don't have a "handle" on them, but you could always find them again by starting back at the head of the list (first) and following the next links.
I was also wondering if first, my original list, will ever be affected by a temporary node list like curr?
The variable first will never be affected by anything other than an assignment statement having first on the left-hand side of the =. On the other hand, the list to which first refers might change quite dramatically or be completely unaffected, depending on what you are using curr for, but first itself can only be affected by assigning a new value to first.
Would the above code modify first or would I have to set first = curr;
The insert and delete code, as given, never modifies first. But it should, if it is going to be able to handle inserting a new node before the current first node, or deleting the current first node. Maybe not with first = curr specifically, but first will definitely need to be updated to reflect a new head of the list. I leave that, as the textbooks say, "as a exercise for the reader".

Iterative method: Delete Linked List node using only one reference variable

SOLVED: CODE REFLECTS SOLUTION
I have been working on a custom Linked List and need to delete a node with a given key only using one reference to the list.
I have managed to do this with two references (Node previous, Node current), but am a bit confused as how to approach this using only one.
My code works for cases except deleting the head node, and nodes that are not in the list ( I get nullpointer exception) when trying to delete '88' or a node that doesn't exist '100'.
Here is my test data from the list:
0) 88
1) 2
2) 1
3) 8
4) 11
// Iterative method to delete a node with a given integer key
// Only uses ONE reference variable to traverse the list.
private void delete (int key, Node x) {
// Check if list is empty
if (isEmpty()) {
System.out.println("Cannot delete; the list is empty.");
}
// Check if we're deleting the root node
if (key == head.getKey()) {
// Now the first in the list is where head was pointing
removeFromHead();
}
// General case: while the next node exists, check its key
for (x = head; x.getNext() != null; x = x.getNext()) {
// If the next key is what we are looking for, we need to remove it
if (key == x.getNext().getKey()) {
// x skips over the node to be deleted.
x.putNext(x.getNext().getNext());
}
} // End for
}
Try this:
public Value delete (int key) {
//check if list is empty
if (head == null)
//the key does not exist. return null to let the method caller know
return null;
//check if we're deleting the root node
if (key == head.getKey()) {
//set the value of what we're deleting
Value val = head.getNode().getValue();
//now the first in the list is where head was pointing
head = head.getNext();
//there is now one less item in your list. update the size
total--;
//return what we're deleting
return val;
}
// general case: while the next node exists, check its key
for (Node x = head; x.getNext() != null; x = x.getNext()) {
//check if the next node's key matches
if (key == x.getNext().getKey()) {
//set value of what we're deleting
Value val = x.getNext().getNode().getValue();
//x now points to where the node we are deleting points
x.setNext(x.getNext().getNext());
//there is now one less item in the list. update the size
total--;
//return what we're deleting
return val;
}
}
//if we didn't find the key above, it doesn't exist. return null to let the
// method caller know.
return null;
}
This is for LinkedList<Value>. General idea is there, but you'll have to tailor this to how you've set everything up.
Well, you have problems with the head and the tail of the list because you are not checking them properly.
You should compare the key the the head before entering the while loop. The first value that the loop checks is of the second node (temp.getNext().getKey()), so you never actually test the head.
Moreover, after the loop has ended and you check to see if the key is in the last node, you are also calling getNext(). If it was indeed the last node, then the next node is null and it has no getKey() method.

Java, LinkedList of Strings. Insert in alphabetical order

I have a simple linked list. The node contains a string (value) and an int (count).
In the linkedlist when I insert I need to insert the new Node in alphabetical order. If there is a node with the same value in the list, then I simply increment the count of the node.
I think I got my method really screwed up.
public void addToList(Node node){
//check if list is empty, if so insert at head
if(count == 0 ){
head = node;
head.setNext(null);
count++;
}
else{
Node temp = head;
for(int i=0; i<count; i++){
//if value is greater, insert after
if(node.getItem().getValue().compareTo(temp.getItem().getValue()) > 0){
node.setNext(temp.getNext());
temp.setNext(node);
}
//if value is equal just increment the counter
else if(node.getItem().getValue().compareTo(temp.getItem().getValue()) == 0){
temp.getItem().setCount(temp.getItem().getCount() + 1);
}
//else insert before
else{
node.setNext(temp);
}
}
}
}
Ok so this is inserting all my strings, but not in alphabetical order. Do you see any error?
public Node findIsertionPoint(Node head, Node node){
if( head == null)
return null;
Node curr = head;
while( curr != null){
if( curr.getValue().compareTo(node.getValue()) == 0)
return curr;
else if( curr.getNext() == null || curr.getNext().getValue().compareTo(node.getValue()) > 0)
return curr;
else
curr = curr.getNext();
}
return null;
}
public void insert(Node node){
Node newNode = node;
Node insertPoint = this.findIsertionPoint(this.head, node);
if( insertPoint == null)
this.head = newNode;
else{
if( insertPoint.getValue().compareTo(node.getValue()) == 0)
insertPoint.getItem().incrementCount();
else{
newNode.setNext(insertPoint.getNext());
insertPoint.setNext(newNode);
}
}
count++;
}
There are a few bugs with your code:
Inserting at/before head actually needs to happen in two different scenarios:
If the list is empty, head becomes node
If the list is not empty, but node is less than the first element, head also becomes node
In either case, node links to whatever head was pointing to before (null or a real node), and head now points to node.
If you're not inserting before head, then you must be inserting after some node. We just need to find where this place is. There are two scenarios:
node.getValue() > temp.getValue(), and node.getValue() < temp.getNext().getValue()
node.getValue() > temp.getValue() and temp.getNext() == null
In either case, node is inserted between temp and temp.getNext()
I suggest encapsulating the after insertion point search in its own function. That is, given the list and a value, it needs to return a node. If that node has the same value as the search value, then simply increment; otherwise, insert after. As a special case, return null to indicate that the insertion point is before head.
In pseudocode, it'll look like this:
FUNCTION findInsertionPoint(Node head, V value) RETURNS Node
// return null if value needs to be inserted before head
IF head == null OR value < head.getValue()
RETURN null;
// otherwise, either return a node with the given value,
// or return a node after which value should be inserted
Node curr = head;
REPEAT
IF curr.value == value
RETURN curr;
ELSEIF curr.getNext() == null OR curr.getNext().getValue() > value
RETURN curr;
ELSE
curr = curr.getNext();
PROCEDURE insert(V value) {
Node newNode = NEW Node(value);
Node insertPoint = findInsertionPoint(this.head, value);
IF insertPoint == null // insert before head
newNode.setNext(this.head);
this.head = newNode;
ELSE
IF insertPoint.getValue() == value
insertPoint.incrementCounter();
ELSE // insert after insertPoint
newNode.setNext(insertPoint.getNext());
insertPoint.setNext(newNode);
Update: I see that you've translated my pseudocode to Java, but for some reason you've omitted codes that deals with inserting before head when head is not empty. Specifically, you have inexplicably omitted this part:
IF head == null OR value < head.getValue()
// ^^^^^^^^^^^^^^^^^^^^^^^^^^
and this part:
IF insertPoint == null
newNode.setNext(this.head); // <<<<<<<<<<<
this.head = newNode;
Both of these are essential; it's what allows "A" to be inserted before the head in [ "B", "C", "D" ].
You need to understand why they're important, and really ask yourself why you chose to remove them. Explain to us, to me, to yourself, why you did that; realize the mistake and learn from it.
For making this, instead of developing from scratch my own sorted list I would implement the Queue interface or extend the already existing PriorityQueue (or any other sorted collection that may apply better). I would define the Node class as an implementation of the Comparable interface or instantiate my queue with a Comparator instance and override the PriorityQueue add method to add the new Node only if another object is not already in the queue, incrementing the counter otherwise. If using java >5.0 for type safety I would use generic to allow just Node objects in the Queue.
I think you want to use one of Multiset implementations from Google Collections.
A Multiset works similar to a Set, but allows for duplicates (and counts them!). Look at TreeMultiset:
A multiset which maintains the
ordering of its elements, according to
either their natural order or an
explicit Comparator.
Without seeing the complete code it's hard to do debugging.
I think the problem is that you set
Node temp = head;
before the loop, but you need to reassign temp while while traversing the list to the current element. In this case you continue to compare against head.
You've taken care of the case when
the list is initially empty. You
should also take care of the special
case when the new node goes at be
beginning of the list. If your list
is B->C->D and you are inserting A.
Its good to set node.next to null(If not already done). So
that if the node gets inserted at the
end, we have null as the next of the
last node.
You need to update the temp to move
to the next node if no insertion is
possible. So you are missing a temp = temp.next;
Since this is homework I'm not going to give you any source code. There is one big issue I see with the code:
Suppose your list already has two distinct items, and you're inserting a new item. In your code, you are checking whether node is greater than head, and if so inserting it immediately after, ignoring the rest of the items in the list.
You code do something like this. There are some missing details which you can fill in yourself.
If list is empty, set head = node, head->next = NULL, and you're done.
Otherwise if node->value < head->value, set node->next = head, head = node.
Otherwise, if node->value == head->value, head->count++;
Otherwise, set tmp = head. While tmp->next->value < node->value, set tmp=tmp->next. (check for nulls!).
If tmp->next == NULL, (i.e. you reached end of list) then set tmp->next = node, and you're done.
Otherwise if tmp->next->value == node->value, (i.e. you reached a node with same value) tmp->next->count++.
Otherwise, if node->next = tmp->next, tmp->next = node, and exit

Categories

Resources