difficulties implementing queue by linked- list in java - java

recently I read an implementation of enqueue in java, and become really confused at the meaning of couple lines in it.
public void enqueue(String item) {
Node oldlast = last;
last = new Node();
last.item = item;
last.next = null;
if (isEmpty())
first = last;
else
oldlast.next = last;
}
I'm confused that since oldlast is created only in this method, why would we state "oldlast.next= last" after else? it would be destroyed after the method, right?
Also, if we only add last to first when first is empty, would it be buggy if I add two nodes then delete two? Since only one node is added to first and I want to delete two would there be exception?

public void enqueue(String item)
{
Node oldlast = last; // last points to some Node_A, oldlast also will point at the same object
last = new Node(); // Now last points to new object (Node_B), old last still points to Node_A
last.item = item;
last.next = null;
if (isEmpty()) first = last;
else oldlast.next = last;
}

oldLast is not created, it simply is a reference to the same object as last.
public void enqueue(String item)
{
Node oldlast = last; // oldLast -> nodeX, last -> nodeX
last = new Node(); // oldLast -> nodeX, last -> nodeY
last.item = item;
last.next = null;
if (isEmpty()) first = last;
else oldlast.next = last; // change the nodeX
}

Related

how to remove last node on a Circular Singly Linked List

I am having problem with removing the last node. it will remove the 2nd to last instead of last.
public Node removeLast() {
if (isEmpty()) {
throw new NoSuchElementException();
}
Node temp = first.next;
if (last.next == last) {
first = null;
} else {
first.next = temp.next;
}
temp.next = null;
length--;
return temp;
}
the "first" is the previous node to last. When i declared it. i pointed the last Node to the last integer and the first Node to the fourth integer. (i have 5 integers). if you need my entire code. please just ask. Thanks
To remove the last we would need a reference to the next to last node. This way we can simply make the next to last node point to the first and update the last node to this next to last node. Java garbage collection will take care of the rest
public Node removeLast() {
if (isEmpty()) {
throw new NoSuchElementException();
}
Node temp2 = first;
Node temp = first.next;
while(temp.next != null) {temp2 = temp; temp = temp.next;}
//now temp 2 should be pointing to the SECOND LAST node
temp2.next = first; //now the second last node points at the first
last = temp2; //our new last node
/*Take care of counters and returns here*/
}
This code wont compile and will throws errors on a list length of 1, you will need to do some edge case checking but this should get you started
The reason why we cant just remove the last node is we need to maintain the circular property of the list

NullPointerException while implementing Queue using Linked List

I am following Coursera Algorithm 1 course, and right now implementing Queues using linked list, but getting a NullPointerException. Please help me out.
package algo_packages;
public class QueueLinkedList {
private Node first, last;
public class Node{
String item;
Node next;
}
public QueueLinkedList(){
first = null;
last = null;
}
public boolean isEmpty(){
return first == last;
}
public void enqueue(String item){
Node oldLast = last;
last = new Node();
last.item = item;
last.next = null;
if(isEmpty()){
first = last;
}
else {
oldLast.next = last;
}
}
public String dequeue(){
String item = first.item;
first = first.next;
if (isEmpty()) last = null;
return item;
}
}
I am getting the exception at:
oldLast.next = last;
oldLast.next caused the NullPointerException when I tried to debug the program.
The first time you enqueue an item isEmpty() returns false, since it checks if first==last, but first is still null and last is no longer null (since you already assigned the new Node to it). This brings you to access oldLast.next when oldLast is null, hence the NullPointerException.
A possible fix :
public void enqueue(String item)
{
Node oldLast = last;
Node newNode = new Node();
newNode.item = item;
newNode.next = null;
if(isEmpty()) { // last is not assigned yet, so isEmpty returns correct result
last = newNode;
first = last;
} else {
last = newNode;
oldLast.next = last;
}
}
When you check isEmpty() it always returns false for enqueue because you are setting last to a new Node() which will never equal first. You don't need to check if list isEmpty() because if list is empty then first == last so you don't need to assign first = last because they are already equal. Try this:
public void enqueue(String item){
Node oldLast = last;
last = new Node();
last.item = item;
last.next = null;
if(oldLast != null)
{
oldLast.next = last;
}
else
{
first = last;
}
}

Inserting Node in a Sorted linked list

The following code ensures that elements are inserted in a linked list in a sorted manner.
After understanding the logic behind this i decided to test it on my own. However when i wrote my version of the code it as follows.
public class SortedList {
private Node first;
public SortedList() {
first = null;
}
public boolean isEmpty() {
return first == null;
}
public void insert(int j) {
Node newNode = new Node(j);
Node previous = null;
Node current = first;
while (current != null && j > current.iData) {
previous = current;
current = current.next;
}
if (previous == null)
first = newNode;
else
newNode.next = current;
previous.next = newNode;
}
public Node remove() {
Node temp = first;
first = first.next;
return temp;
}
public void displayList() {
System.out.println("First to -----> Last");
Node current = first;
while (current != null) {
current.display();
current = current.next;
}
}
}
NODE CLASS
public class Node {
public int iData;
public Node next;
public Node(int id) {
iData = id;
}
public void display() {
System.out.println(iData + " ");
}
}
TEST CLASS
public class SortedListApp {
public static void main(String[] args) {
SortedList list = new SortedList();
list.insert(20);
list.insert(40);
list.displayList();
list.insert(10);
list.insert(30);
list.insert(50);
list.displayList();
list.remove();
list.displayList();
}
}
The only difference between the two is that in my version when the while loop terminates. I first set the next value of the newNode to the current and then i set the next value of previous to the new Node. In the original code posted they have it reversed. For some reason this throws Null Pointer Exception. I am wondering why?
From what i understand, once the new node finds its place for insertion. We have reference to the previous node and the current node and we are trying to insert the new node in the middle of the previous and the current. Therefore what i do is set the next of the new Node to the current and then i set the next of previous node to the new node.
Please tell me where i am wrong.
Trace through this code when previous is null:
if (previous == null)
first = newNode;
else
newNode.next = current;
previous.next = newNode;
Notice that you never actually changed previous in the if statement, so this will try to write the next field of null, causing the crash.
If previous is null, then you need to prepend the node to the list, and in that case all you need to do is set first to newNode and make newNode's next pointer point to the old list. In the case where previous isn't null, then you need to do two rewirings: you need to make previous.next point to the new node and for the new node's next pointer to point to the current node. You can fix this by writing
if (previous == null) {
newNode.next = current;
first = newNode;
}
else {
newNode.next = current;
previous.next = newNode;
}
Equivalently:
newNode.next = current;
if (previous == null)
first = newNode;
else
previous.next = newNode;
Hope this helps!

Why is my doubly linked list removing previous links?

I Know this topic has been beat to death but I'm really struggling with implementing these two add methods to a linked list. addFirst and addLast both work when called by themselves but when I call addFirst("foo") and addLast("bar") the add last removes anything previously added to the list. add first is supposed to add an item to the beginning of the list, and add last is supposed to append it to the end.
import java.util.Iterator;
import java.util.NoSuchElementException;
public class Deque<Item> implements Iterable<Item> {
private int N;
private Node first;
private Node last;
//create linked list
private class Node
{
String item;
Node next;
Node previous;
}
public Deque() // construct an empty deque
{
N = 2;
first = new Node();
last = new Node();
//link together first and last node;
first.next = last;
last.previous = first;
last.item = "Last";
first.item = "First";
}
public boolean isEmpty() // is the deque empty?
{
return first == null;
}
public int size() // return the number of items on the deque
{
return N;
}
public void addFirst(Item item) // insert the item at the front
{
Node nextElement = new Node();
nextElement.item = (String)item;
nextElement.next = first.next;
nextElement.previous = first;
first.next = nextElement;
N++;
}
public void addLast(Item item) // insert the item at the end
{
Node newLast = new Node();
newLast.item = (String)item;
newLast.next = last;
newLast.previous = last.previous;
last.previous.next = newLast;
last.previous = newLast;
N++;
}
public void printList()
{
Node print = first;
for (int i = 0; i < N; i++)
{
System.out.print(print.item);
print = print.next;
}
System.out.println("");
}
Seems like you're getting yourself confused. Generally, if your doing something.next.next or similar, a warning should go off in your head. You'd also be well served to provide a constructor that could take the item instead of the addition statement in the method.
public void addLast(Item item) // insert the item at the end
{
Node newLast = new Node();
newLast.item = (String)item;
if (isEmpty()) {
first = newLast;
} else {
last.next = newLast;
newLast.previous = last;
}
last = newLast;
N++;
}
As far as addFirst is concerned, so you don't inadvertently get bad advice, it would go something like this...
public void addFirst(Item item) {
Node newFirst = new Node();
newFirst.item = (String)item;
if (isEmpty()) {
last = newFirst;
} else {
first.previous = newFirst;
}
newFirst.next = first;
first = newFirst;
N++;
}
The addfirst method is missing updating one of the pointers
public void addFirst(Item item) // insert the item at the front
{
Node nextElement = new Node();
nextElement.item = (String)item;
nextElement.next = first.next;
nextElement.previous = first;
first.next.previous = nextElement; //ADDED HERE
first.next = nextElement;
N++;
}
I think this question is answered with one simple link - you're re-inventing the wheel which is always a bad idea, no matter what educational purposes your goals serve.
Use the Deque interface.

Delete a last node of linked list given pointer to that node

I'm trying to delete the last node of the linkedlist, given pointer only to that node.
I wrote the below implementation, but isn't working.
I already visited majority of SO questions regarding this subject, but none of them shows how to delete last node of linked list, if there's only one pointer to that node ?
Am I missing anything here ?
class Node {
Node next;
int value;
Node(int val) {
this.value = val;
this.next = null;
}
#Override
public String toString() {
Node cur = this;
String str = "";
while(cur != null) {
str += cur.value+"->";
cur = cur.next;
}
return str;
}
}
class DeleteNodeLL {
public static void deleteNode(Node current) {
Node temp;
if(current.next == null) {
current = null;
return;
} else {
current.value = current.next.value;
temp = current.next;
temp = null;
current.next = current.next.next;
}
}
public static void main(String [] args) {
Node n1 = new Node(25);
Node n2 = new Node(1);
Node n3 = new Node(36);
Node n4 = new Node(9);
Node n5 = new Node(14);
n1.next = n2;
n2.next = n3;
n3.next = n4;
n4.next = n5;
n5.next = null;
System.out.println("Original linkedlist :");
System.out.println(n1);
System.out.println();
System.out.println("After deleting a node :");
deleteNode(n5);
System.out.println(n1);
}
}
Output :-
Original linkedlist :
25->1->36->9->14->
After deleting a node :
25->1->36->9->14->
With the singly linked list it is not possible.
This is the interview questions which is typically asked in Big Shot companies which emphasizes on Data Structures.
The question is formulated as "Delete the node in single linked list given pointer to only that node"
Expected Solution:
public void deleteNode(Node n)
{
if(n==null || n.next==null)
{
System.out.println("Delete not possible");
return;
}
n.data = n.next.data;
Node tmp = n.next;
n.next = n.next.next;
tmp.next = null;
System.out.println("Node Deleted");
}
The idea is to copy the data from the next node to the current node and delete the next node. The solution does not work if the node is the last node (This is what candidate has to debate and point out in interview)
Hope it helps you! (Solution to your problem is a trick question, and it does not exists)
current = null; doesn't do what you expect - it only sets local variable (method argument) to null.
What you want is impossible with your current implementation of the Node class.
You need either a reference to the previous node inside the Node class (i.e. a doubly-linked list) or you have to provide a reference to some previous node to the deleteNode method.
I would say
You can delete the last node from the Linked List if reference of
it's previous node is given.
However it's based on how you implement the list.
For your implementation, you can't do that
The only solution to this question is to iterate over the complete list keeping the prev node pointer everytime, compare the current node with the present node. When the comparison passes, delete the last node, and point the prev node to null. Something like the code below(note: I did not compile it)
deleteNode(Node *node){
if(node){
currentNode = Head, prevNode = NULL;
while(currentNode != node){
prevNode = currentNode;
currentNode = currentNode -> next;
}
delete currentNode;
prevNode -> next = NULL;
}
}
#asifsid88 copied and pasted the solutions from "cracking the coding", you should refer to that book to find more interesting and challenging questions.

Categories

Resources