Single Linked List Insert at the tail - java

Every time I run this, it returns a bunch of: null, null, null for the items when I test the function out.
//enqueue()
//adds newItem to the back of this Queue
public void insertItemLast(Object newItem){//make sure that it is not empty so we can do the cool stuff in here
if(newItem == null)
return;//user inputs nothing
else {
Node P = new Node(newItem);
P.next = null;
if(head == null){
head = P;
tail = P;
//tail.next = null;
}else{
tail.next = new Node(newItem);
tail = new Node(newItem);
//tail.next = null;
}
}
numItems++;
}//end enqueque

You create two different links instead of just one.
Your else should be :
} else {
tail.next = new Node(newItem);
tail = tail.next;
}
Actually, you can make it even simpler. Just use P for the new link of the list in all cases :
public void insertItemLast(Object newItem){
if(newItem == null)
return;//user inputs nothing
else {
Node P = new Node(newItem);
P.next = null;
if(head == null) {
head = P;
tail = P;
} else {
tail.next = P;
tail = P;
}
}
numItems++;
}//end enqueque

You correctly assigned a new Node to tail.next, but you didn't update tail; you instead assigned another new Node to tail, effectively breaking the tail off of the list.
To advance the old tail to the new tail -- the newly inserted Node -- replace
tail = new Node(newItem);
with
tail = tail.next;

Related

LinkedList Algorithm

Here is a implementation of LinkedList algorithm. Algorithm inserts node at beginner, after a given node, or at the end of list.
package LinkedList;
class LinkedList {
Node Head;
class Node {
int data;
Node Next;
public Node(int d) {
data = d;
Next = null;
}
}
public void insert(int value) {
if (Head ==null) {
Head = new Node(value);
return;
}
Node new_node = new Node(value);
new_node.Next = Head;
Head = new_node;
}
public void display() {
Node a = Head;
while (a != null) {
System.out.println("value:" + a.data);
a = a.Next;
}
}
public void insertMiddle(int valueToInsert, Node prev_node) {
if (Head == null) {
System.out.println("Cant put value after last node");
}
Node new_node = new Node(valueToInsert);
new_node.Next = prev_node.Next;
prev_node.Next = new_node;
}
public void last(int value){
Node new_node = new Node(value);
if(Head == null){
Head = new Node(value);
return;
}
new_node.Next = null;
Node last = Head;
while(last != null){
last = last.Next ;
}
last = new_node;
return;
}
}
public class LinkedList_Insertion {
public static void main(String[] args) {
// TODO Auto-generated method stub
LinkedList list = new LinkedList();
list.insert(8);
list.insert(20);
list.insert(0);
list.insertMiddle(999, list.Head.Next);
list.display();
System.out.println("--------------");
list.last(10000);
list.display();
}
}
In the above code, While using method insert:
public void insert(int value) {
if(Head ==null){
Head = new Node(value);
return;
}
Node new_node = new Node(value);
new_node.Next = Head;
Head = new_node;
}
why don't we use Head.next = new_node;
Similarly, for method :
public void last(int value){
Node new_node = new Node(value);
if(Head == null){
Head = new Node(value);
return;
}
new_node.Next = null;
Node last = Head;
while(last != null){
last = last.Next ;
}
last = new_node;
return;
}
why don't we use last.next = new_node;?
I often end up doing same mistake again and again. If someone can clear this concept, I will be grateful.
Looking forward to your response!
Head case:
You can have Head->node1->node2->node3->...->lastNode
If you do Head.next = newNode, then node1->node2->node3->...->lastNode will be lost.
If you had a doubly-linked list, you could do Head.prev = newNode; Head = Head.prev (prev means previous).
Last case:
This code:
public void last(int value){
Node new_node = new Node(value);
if(Head == null){
Head = new Node(value);
return;
}
new_node.Next = null;
Node last = Head;
while(last != null){
last = last.Next ;
}
last = new_node;
return;
}
looks weird, the condition should actually be while (last.next != null), but even then you are not inserting, you first get a reference to the element that is last in your list, then you make that reference point to another object, it should actually be last.next = newNode, you are right.
Implementing linked lists is a good way to understand how java references work, keep practicing and also try to implement a doubly-linked list.
Your Second Code seems to be wrong, You are right it has to be last.next = newNode
now answering your 1st question consider 3 nos in linked list 100(head),200,300.
here head node with value 100 points to next node with value 200 which must in turn point to the node with value 300. Now let us suppose you want to insert 50 before 100, so when you do
Head.next = new_node;
The node with value 100 is made to point to next node with value 50, so now we have 100,50 in the linked list with the head as 100 still which is wrong
so we do
new_node.Next = Head;
Head = new_node;
In this case linked list becomes 50,100,200,300.
Thus we do it this way.

Linked List, keep getting NullPointerException

I am trying to add Point into a linked list, in order to keep track of the frequency of each data entry. Everytime I run this code it gives me a NullPointerException. I don;t understand why, to me it seems as if after it adds the frequency it creates a gap but I cant seem to fix it.
if(firstNode == null)
{
addPair = new Pair(aData, 1);
firstNode = new Node(null, addPair, null);
lastNode = firstNode;
currentNode = firstNode;
numberOfNodes++;
}
else
{
currentNode=firstNode;
for(int count = 0; count<numberOfNodes; count++)
{
if(currentNode.data.fst().equals(aData))
{
addPair = new Pair(aData,currentNode.data.freq()+1);
if(count==0)
firstNode= new Node(currentNode,addPair,null);
currentNode = new Node(currentNode,addPair,null);
break;
}
if(count == (numberOfNodes-1) && currentNode.data.fst() !=(aData))
{
addPair = new Pair(aData,1);
Node newNode = new Node(currentNode, addPair, null);
currentNode.next = newNode;
lastNode = newNode;
numberOfNodes++;
break;
}
currentNode = currentNode.next;
}
}
numberOfEntries++;
private class Node
{
private Node previous;
private Pair data;
private Node next;
private Node(Node previousNode, Pair<T,Integer> addPair, Node nextNode)
{
previous = previousNode;
data = addPair;
next = nextNode;
}
}
If you are receiving a NPE at the line if(currentNode.data.fst().equals(aData)) then either currentNode == null or currentNode.data == null or currectNode.data.fst() == null. The first thing to do in diagnosing the problem is to find out which of these is the case. I suggest you put the following statements before this line and rerun your code:
assert currentNode != null;
assert currentNode.data != null;
assert currentNode.data.fst() != null;
Apart from that diagnosis there are a number of ways you could make your code safer. Firstly you really have no need to use a count to iterate through your linked list. Much safer would be to end when the next pointer is null:
for (Node current = firstNode; current != null; current = current.next) {
if (current.data.equals(aData)) {
// increment counter
return;
}
}
The main problem is in this line
firstNode= new Node(currentNode,addPair,null);
When you increase frequency of first node you are not setting the next Node, so you got list of only one node, but with size of many. Similar problem with line
currentNode = new Node(currentNode,addPair,null);
Also all first if statement is wrong. You are corrupting links in the list, it should be something like this
if (currentNode.data.fst().equals(aData)) {
addPair = new Pair(aData, currentNode.data.freq() + 1);
// create new node
Node c = new Node(currentNode.previous, addPair, currentNode.next);
// set links to new node
if (currentNode.previous != null) {
currentNode.previous.next = c;
}
if (currentNode.next != null) {
currentNode.next.previous = c;
}
if (count == 0) {
firstNode = c;
}
break;
}
To simplify your code and decrease possible errors I could recommend to write some function like incFrequency() in Pair class. Then in the loop do something like this
if (currentNode.data.fst().equals(aData)) {
currentNode.data.incFrequency();
break;
} else if(count == (numberOfNodes-1) && currentNode.data.fst() !=(aData)) {
// add new node to the end
}
Also you could rewrite you for loop
currentNode = firstNode;
// iterate through list
while (currentNode != null) {
// process currentNode
...
// move to the next node
currentNode = currentNode.next;
}

push(Element) method implementation in Stack

I am learning Stack today.
I am trying to implement push(Element) method, but for some reasons it is not working.
I have added 10 items to my stack, then using toString method I print. The only item prints is my most Top Element.
Your help would be greatly appreciated!.
private Node head = null;
private Node tail = null;
private static int size;
public void push(Customer custPair)
{
if (head == null)
{
head = new Node(custPair, null);
tail = head;
size++;
} else
{
tail.next = head;
head = new Node(custPair, null);
size++;
}
}
#Override
public String toString()
{
StringBuilder sBuilder = new StringBuilder();
// Walk down the list and append all values
Node curNode = head;
while (curNode != null)
{
sBuilder.append(curNode.value.toString()).append("\n");
curNode = curNode.next;
}
return sBuilder.toString();
}
Your logic is wrong when the stack already has a head. I think the new head must point to old head (via .next).
I'm bit confused, are you implementing a LIFO or FIFO stack?
For a LIFO
else {
Node node = new Node(custPair, null);
node.next = head;
head = node;
size++;
}
For a LIFO Stack, you really don't need a tail.

adding at the end of a singly-linked list in constant time

I'm trying to write a method for adding at the end of a singly linked list in a constant time. I don't know how to assign a pointer to the last node in the list in constant time. This method runs in 0(n):
public void insertEnd(Object obj) {
if (head == null) {
head = new SListNode(obj);
} else {
SListNode node = head;
while (node.next != null) {
node = node.next;
}
node.next = new SListNode(obj);
}
size++;
}
This is a beginning of my new method:
public void addLast(SListNode obj){
//if the list is empty, the new element is head and tail
if(tail == null){
obj.next = null;
head = tail = obj;
}else{ -----> here I'm confused
}
}
This is my SList class:
public class SList {
private SListNode head;
private SListNode tail;
private int size;
public SList() {
size = 0;
head = null;
tail = null;
}
I think this should cover it: (should go in the else)
tail.next = obj; // have (the current tail).next point to the new node
tail = obj; // assign 'tail' to point to the new node
obj.next = null; // may not be required
You have to implement a Double Ended Queue that allow to insert at head or at tail of your List
If your List is empty, both head and tail are null, if it contains one element head == tail
public void addLast(SListNode obj){
//if the list is empty, the new element is head and tail
if(tail == null){
obj.next = null;
head = tail = obj;
}else{ -----> here I'm confused
tail.next = obj;
tail = obj;
}

Java Linked List - add method

Data structures class, implementing a singly linked-list with head, tail and current nodes. Having trouble with a method, could use a nudge in the right direction.
From the assignment, write the method:
add( item ) : adds the item (String) after the current node in the list and sets the current pointer to refer to the new node.
My attempt:
public void add(String item)
{
if(curr != null)
{
Node newNode = new Node(item, curr.next);
curr.next = newNode;
curr = newNode;
}
else
{
head = tail = new Node(item, null);
curr = head;
}
}
My add method only seems to work when I'm adding items to the middle of the list, not on either end. If I use it to add a few items and then print the list, only the first one I added will be on the list, while my prepend and append methods have tested just fine.
Is there any glaring issue with my code? I feel like I'm missing something obvious.
All:
public class LinkedList {
Node head = null; /* Head of the list */
Node tail = null; /* Tail of the list */
Node curr = null; /* Current node in the list */
public void prepend(String item) {
if (head == null) {
head = tail = new Node(item, null);
curr = head;
} else {
head = new Node(item, head);
curr = head;
}
}
public void append(String item) {
if (head == null) {
head = tail = new Node(item, null);
curr = tail;
} else {
tail.next = new Node(item, null);
tail = tail.next;
curr = tail;
}
}
public void add(String item) {
if (curr != null) {
Node newNode = new Node(item, curr.next);
curr.next = newNode;
curr = newNode;
} else {
head = tail = new Node(item, null);
curr = head;
}
}
public void delete() {
if (curr.next == null) {
Node temp = head;
while (temp.next != curr) {
System.out.println(temp.item);
temp = temp.next;
}
temp.next = null;
curr = head;
}
}
public void find(String item) {
Node temp = new Node(curr.item, curr.next);
if (item.equals(temp.item))
curr = temp;
else {
temp = temp.next;
while (temp.next != null && temp != curr) {
if (item.equals(temp.item))
curr = temp;
}
}
}
public String get() {
if (curr != null)
return curr.item;
else
return "";
}
public boolean next() {
if (curr != tail) {
curr = curr.next;
return true;
} else
return false;
}
public void start() {
curr = head;
}
public void end() {
curr = tail;
}
public boolean empty() {
if (head == null)
return true;
else
return false;
}
}
Node class:
class Node {
Node next;
String item;
Node(String item, Node next) {
this.next = next;
this.item = item;
}
}
There is indeed a problem in add: it doesn't update tail when nodes already exist. Consider this sequence of actions:
LinkedList list = new LinkedList();
list.add("one");
list.add("two");
list.append("three");
If you were to then print it using this:
public void print() {
Node curr = this.head;
while(curr != null) {
System.out.println(curr.item);
curr = curr.next;
}
}
Like this:
list.print();
You'd get the following output:
one
three
This happens because tail -- which append relies on -- continues to point to the first Node after the second add operation is performed.
I don't see any problems here, so I would guess the issue is elsewhere.
Okay, the only issue I see there is in delete:
public void delete()
{
Node temp = head;
while(temp != null && temp.next != curr) {
System.out.println(temp.item);
temp=temp.next;
}
if (temp != null && temp.next != null) {
temp.next = temp.next.next;
}
curr = head;
}
I think I have found your problem.
If you use append() you add it directly after the tail. But when you have added previous nodes after the tail you don't set your tail to the new node. This means that once you call append() twice you loose all the nodes that you have added after the first append().
Brief example:
public static void main(String[] args) {
LinkedList list = new LinkedList();
list.add("First add");
list.append("First Append");
list.add("Second add");
list.prepend("First prepend");
list.add("Third add");
list.prepend("Second prepend");
list.add("fourth add");
list.append("Second Append");
list.add("Fifth add");
list.add("Sixth add");
list.start();
do {
System.out.println(list.get().toString());
} while (list.next());
}
Output:
Second prepend
fourth add
First prepend
Third add
First add
First Append
Second Append
Conclusion: "Second Add" is lost, as well as "Fifth add" and "Sixth add" because your next() method stops as soon as it reaches the tail. You need to always update the tail if you add a new node in the end.
Hope this helps.
Cheers, Chnoch
I think the problem is
if (curr != null) {
Node newNode = new Node(item, curr.next); //<-- here (curr.next)
//and
Node(String item, Node next) {
this.next = next; //<-- here
Try (Edited):
Node newNode = new Node(item, curr); // pass curr to the constructor of Node
curr = newNode;

Categories

Resources