Not clear why "start" is assigned/gives reference at line 1 - java

This is a issue of single linked list implementation.
Say, A class Node is defined.
Now, for operations another class LinkedList is defined. We are going to add element at start position.
class LinkedList {
protected Node start;
protected Node end;
public int size;
public LinkedList() {
start = null;
end = null;
size = 0;
}
//method for insert at start
public void insertAtStart(int value) {
Node nptr = new Node (value, null);
size++;
if (start == null) {
start = nptr;
end = start; //Line 1
}
}
// others method(omitted here)
}
I was thinking, what would happen if we assign nptr itself to end in Line 1? I am not getting clear in that issue.

After this line:
start = nptr;
the variable start holds the reference to the same object as nptr, i.e. the object created during:
Node nptr = new Node (value, null);
So it doesn't matter if you call end = start or end = nptr as end will contain the same reference afterwards; nptr, end and start will all point to the same object.

In this case the end reference variable should be updated only for first call of insertAtStart(int val) to maintain the reference to the end node.
if you assign nptr itself to end in Line 1, the end reference variable will have the reference to newly added node (Which is the first node of the list).

Related

NullPointerException error when trying to find last item's value in a linked list

I'm still a beginner in Java - I'm trying to create a method that finds the value of the last item in a linked list, and it's throwing a java.lang.NullPointerException error, and it indicates the error is on line 21. From my understanding, a null pointer exception happens when the programmer is calling a reference-type variable to reference basically nothing, since the variable hasn't been declared yet.
For example, if I write Integer k;, I cannot call on k until I declare: k = new Integer(10);. If I write int k;, Java automatically sets the value to 0, since it's a primitive type, and I will be able to call it directly.
In this case, I kind of understand why it's throwing this error, since as you can see in the second line of the getLast() method, I called next, which should be null, since it hasn't been declared yet. However, it's indicating that the error is on line 21, where I reassign last. Why?
How do I fix this code? FYI this is just a practice problem through my school's website, and the task was to complete the getLast() method.
/*
* Class for representing a linked list of ints.
*/
public class List {
public int value;
public List next;
public List(final int setValue) {
value = setValue;
}
/**
* Return the value of the last item in the list.
*/
public int getLast() {
List current = next;
int last = next.value;
while(next != null) {
current = next;
next = current.next;
last = next.value; //ERROR
}
return last;
}
}
You should move the statement that moves to the last node as the last statement of the while loop so that on the next iteration, the loop condition would become false and the loop terminates. In your case, you try to access the next element after you reach the end of the list.
Also, you must use the local variable current for iterating and not assign / change the instance variable next. If you call getLast the next time, it won't work because next now points to null.
Change it as
List current = next;
int last = value;//Set to the current value to begin with
while(current != null) {
last = current.value;
current = current.next;
}
return last;
When the while loop gets to the last node you set next to null with:
next = current.next
You should be able to fix by setting last = current instead of next.
But you should be careful about empty lists. It seems that if you called getLast() on an empty list you'd have a NullPointerException again.
NullPointerException is thrown because next is null and you reference next.value.
You should not change next, use a temporary value to iterate to the end of the list.
public int getLast() {
if (next == null)
return value;
List current = next;
while (current.next != null)
current = current.next;
return current.value;
}

explain Linked List data structure in Java

Iknow java is passed by value. For linked list data structure, what is the difference between method size() and size1()? I think there are the same becasue the head and next reference point to the same thing in size1(). but the result is difference
public class IntList {
int item;
IntList next;
public IntList(int item, IntList next){
this.item = item;
this.next = next;
}
public int size(){
int size = 1;
while (next !=null){
size++;
next = next.next;
}
return size;
}
public int size1(){
int size = 1;
IntList head = next;
while (head != null){
size++;
head = head.next;
}
return size;
}
public static void main(String[] args) {
IntList L = new IntList(1,null);
L = new IntList(2,L);
L = new IntList(3,L);
L = new IntList(10,L);
L = new IntList(20,L);
System.out.println(L.size());
}
}
I am confused about the reference means in java.
This is a matter of issue with scope. In size1(), you are creating a local variable named head. When you call size1() it creates a reference variable that will be destroyed at the end of the call. This means that no matter how many times you call size1(), it will always give you the proper size.
However, when you use the field "next" in size(), it iterates through each variable until the end. However, once it gets there, it is notdestroyed because its scope is the object. This means the next time you call size(), and all subsequent calls (given no changes), it will always return 1.
They're logically the same, but size() is actually pointing next to the final node, so the next size check will return 1. size1() uses a local variable to traverse the list, so the object state isn't affected.

Building a linked list in Java

This is an example from my book. As I see it, when you create a list with this class, you create two objects (first and last, which are null). I can't figure out why, when you put both first and last "Node" objects in the add method. Shouldn't it create two elements when you set both first = n and last = n. For example, if I call list.add(2), shouldn't both first and last be 2 now ?
public class List {
private Node first = null;
private Node last = null;
public List(){
first = null;
last = null;
}
private static class Node{
public int value;
public Node next;
public Node ( int value, Node next){
this.value = value;
this.next = next;
}
}
public void add (int value){
Node n = new Node (value,null);
if(first==null){
first = n;
last = n;
}else{
last.next = n;
last = n;
}
}
public int size(){
int number = 0;
Node n = first;
while(n != null){
number++;
n = n.next;
}
return number;
}
}
As i see it, when u create a list with this class, you create two objects (first and last, which are null).
That's not true. first and last are not objects, but references to objects. And in this case, they start out as null references, meaning that they don't refer to any object at all.
When you write first = n; last = n;, you set first and last to both refer to the same object — whatever object n refers to.
For example, if list.add(2), shouldn't now both first and last be 2?
Yes, they'll both refer to the same Node instance, whose value is 2.
Yes i see that first and last are needed. Probably later on first will be much more useful if you have dequeue (remove first) or a search (which i guess can be done from the end rather than at the start, same process for a simple linear search).
As for your question. Yes if you started with a blank list and said list.add(2). Both first and last will be pointing to node with value 2. This is because the first element and the last element in the list are the same, hence 1 element in the list. Its both first and last (and middle if you want to be weird).
but if you did list.add(1), list.add(2). You would get first = node.value == 1 and second = node.value == 2

java linked list copy constructor

Im having trouble with a constructor for a linked list. it takes a string and is supposed to create a node for every character.
i get a nullpointerexception everytime i try to print out the list. Does that mean that not even the first node is being created?
below is my node class and the list constructor.
class CharNode {
private char letter;
private CharNode next;
public CharNode(char ch, CharNode link)
{
ch = letter;
link = next;
}
public void setCharacter(char ch)
{
ch = letter;
}
public char getCharacter()
{
return letter;
}
public void setNext(CharNode next)
{
this.next = next;
}
public CharNode getNext()
{
return next;
}
}
and this is my constructor
// constructor from a String
public CharList(String s) {
CharNode newNode = head;
for(int i = 0; i <s.length(); i++)
{
newNode = new CharNode(s.charAt(i), null);
newNode.setNext(newNode);
}
}
am i constructing it correctly?
First of all, your attributions are switched around!
ch = letter;
link = next;
should be
letter = ch;
next = link;
Same thing in your setter.
When you have a method in Java of the form:
public void setSomething(String argument){
this.classMember = argument;
}
Is usually what you want. You must assign your argument to your class member, not the other way around.
Also, when you're invoking your constructor, you have:
newNode = new CharNode(s.charAt(i), null);
newNode.setNext(newNode);
This make it so that your "link" is always pointing to itself! Think about what you need to do to make the previous Node point to the node you've just created (perhaps save it somehow?)!
Was I clear enough? Let me know if I can explain further.
As pcalcao said, = assigns the value on the right to the variable on the left. You'll need to change ch = letter; to letter = ch; and link = next; to next = link;
Now, the line CharNode newNode = head; doesn't mean anything unless you've specified what head is prior to the code you've given, but it doesn't look like it. Remember that when creating a linked list, you don't start with anything, so even "special" nodes like head must be created (instantiated, if you prefer). The idea is to create the first node (the head), and then assign head to that first node. For every node after the first one, this step isn't required, as you simply are adding to the end of the list.
Finally, during construction, you'll need a reference to both a new node (like you have now), and the previous node, in order to do proper appending. Your code now is simply setting the next node in the list to the current node, which means that once you create a new newNode, you will lose the reference to the previous newNode.
A good way to approach linked lists when one is first getting started is to draw out what you want to do step by step, then try and translate that into code. Hopefully this is helpful.

Manual Linked List - Insert before method

This is part of an exercise we did in class, I just can't figure it out...
The required method is the insertBefore(object data) method wherein when a user choose this method it will prompt it to enter a data to be inserted before the reference data(input by user)
An example of how it should run:
// assuming linked list has data 1,2,3 inserted already
Choose Method:
1)Insert Before
choice: 1 // input by user
====Insert Before====
Enter Reference data: 2 // input by user
Enter Data to be inserted: 5 // input by user
supposed output: 1,5,2,3
Here's my code for this exercise: (This is inside a class called LinkList with variables
protected int end;
protected Node start;
and an inner class called Node)
private class Node
{
public char data;
public Node next;
public Node(char data)
{
this.data = data;
}
}
public void insertBef(char ref,char data)
{
Node temp = new Node(data);
Node current = start;
if(end!=0)
{
for(int i = 1; i<end; i++)
{
if(current == start)
{
Node newNode = start;
newNode.data = current.data;
newNode.next = temp;
current = current.next;
}
else if(current.data == ref)
{
Node newNode = current;
newNode.data = current.data;
newNode.next = temp;
current = current.next;
}
}
end++;
}
else
{
temp.next = start;
start = temp;
}
end++;
}
But when I run my code it ouputs 3,5, not 1,5,2,3! I can't see where I might have gone wrong...
Can someone please tell me where the mistake is, and explain how I might fix it?
I understand that to be able to insert before a reference value you should:
Make a new node for the new data
Make a temporary node for the reference value and link
Make the link of the data before the reference value point to the new node and make the link of the new node point to the temporary node
I just can't seem to figure out how to implement it in Java code...
When programming, if it seems hard, you're probably going about it the wrong way...
You only need one line of code to accomplish the task!
list.add(list.indexOf(reference), data);
Here's this line wrapped as an insertBefore method:
public static void insertBefore(List<Integer> list, int reference, int data) {
list.add(list.indexOf(reference), data);
}
Here's a test using your example:
public static void main(String[] args) {
List<Integer> list = new ArrayList<Integer>(Arrays.asList(1, 2, 3));
insertBefore(list, 2, 5);
System.out.println(list);
}
Output:
[1, 5, 2, 3]
Note: This code will throw an exception if the reference element is not found.
I'll leave it to you to plug that hole.
First things first: for loops are generally a bad idea with linked lists. while loops are much better; you can do something like while(next != null).
Looking at your code, you seem to have a few problems.
Your for loop is overly complicated, and doesn't seem to make a lot of sense. Here's how your loop should look:
Get head node
Begin looping through the list, checking the next node's value as you go
Once you find that the next node's value is the one you're looking for, creating a new node.
Insert the new node by setting its Next value to be equal to the current node's Next value, then set the current node's next value to be the new node.
Return from the function.
Your middle bullet point is actually unnecessary, and I have no idea what you use end for. Regardless, you seem to have the basic principle down, so I won't feel like I'm spoiling you by posting code.
Now, I'm not sure what your start is. Does it hold a value, or is it a dedicated head node? I'd vote for a dedicated head node, I generally find it easier to work with because you don't need to add code for a special case where the number should come before the head. So your start node should be "empty"; the value it holds is ignored, the only thing it's used for is to keep a pointer to the first legit node in the list. If you do this, the insertBef method becomes incredibly simple. NOTE: untested code to follow.
public void insertBef(char ref, char data)
{
Node current = start;
while( current.next != null )
{
if( current.next.value == ref )
{
Node n = new Node(data);
n.next = current.next;
current.next = n;
return;
}
current = current.next;
}
}
Please don't just copy the code. If you have questions, post them and I'll do my best to answer.

Categories

Resources