explain Linked List data structure in Java - 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.

Related

Understanding setup for doubly linked list in Java

I am working on a doubly linked list in Java. So that I can create functions, I'm first working to understand the setup.
I have this code. I have started comments with what each line does. Looking at tutorials and I want to make sure I understand this correctly. I still get a little confused on using classes.
If I create a new node by Node x = new Node(); - I am creating a new node of class Node. So that creates an instance using "static class Node {"
Each Node created contains a int item, Node next, and Node prev, that I will set in my functions. The int item I assume is the contents of the Node.
What does the line "public Node() {}" do?
public class MyDeque {
Node first = null; //instance variable, first is of type node and is set to null
Node last = null; //instance variable, last is of type node and is set to null
int N = 0; //keeping track of number of nodes
static class Node {
public Node() { }
public int item;
public Node next; //next is of type node
public Node prev; //prev is of type node
}
To understand this setup for Double-Linked-List you need to understand how a constructor works; A constructor is like a method, which is used to initialize properties of a class when the object of this class is initialized in memory for the first time.
Let's take your code for an example, I modified it in a proper way to understand why and how constructors used in Java -
public class MyDeque {
Node first;
Node last;
int N;
public MyDeque(){
this.first = null;
this.last = null;
this.N = 0;
}
static class Node {
int item;
Node next;
Node prev;
public Node() {
this.next = null;
this.prev = null;
}
public void setItem(int item) {
this.item = item;
}
public int getItem(){
return this.item;
}
// ... public getters for other items
}
As you can see two constructors public Node(){} and public MyDeque(){} are used to set values for the properties of those objects when they are initialized in memory for the first time.
Later, of course, you can set / unchange / change values of properties using the setter method or using the "." operator but remember constructor will always take place when the objects are initialized or reinitialized in memory for the first time.

Singly Linked List pass by value

Hi i am learning linked list in java. Its a simple doubt but couldn't figure out.
class Node{
int data;
Node next;
Node(int data){
this.data = data;
this.next = null;
}
//java main method
Node head = null;
Node newNode = new Node(1);
head.next = newNode;
Here i am passing the reference of the newNode to the next field in the Node class. The next is holding the reference of the newNode.
In dart programming languages objects are passed via call by value. By doing the above code is also working fine. My question is can we implement the Node field inside the Node class with either by reference or value.
In the context of c++, I don't know much c++ syntax but roughly it looks like this
//with pointer
class Node{
public:
int data;
Node* next;
}
It is possible to implement the above code like this one
//without pointer
class Node{
public:
int data;
Node next;
}
As stated by the other answers, your code wont work since your head variable is null and thus would throw a NullPointerException.
Your main method should like this:
Node head = new Node(0);
Node newNode = new Node(1);
head.next = newNode;
Java is always passing references by value. For a comprehensive answer see https://stackoverflow.com/a/40523/19799529
Pass-by-value
Java is always passing by value (as you are accustomed to):
int x = 3; f(x);
Object y = new Object(); g(y);
Above neither f nor g can alter the passed variables x and y.
The variables are just memory slots in which the value is stored, and that value is passed (not which memory slot), whether primitive type (int) or class instance (Object).
Linked list
Your Node class is fine.
public class SingleLinkedList {
Node head;
int count;
public int size() {
return count;
}
It is worth holding the Node inside a list class, possibly with a field for the number of elements. You could use that for index checking.
public void add(int i, int data) {
head = addToNodes(head, i, data);
++count;
}
private Node addToNodes(Node link, int i, int data) {
if (i <= 0 || link == null) {
Node node = new Node(data);
node.next = link;
return node;
}
link.next = addToNodes(link.next, i - 1, data);
return link;
}
Above I have used a recursive method. It shows that as the passed variable (head or some node's next field) cannot be changed in java, one has to return it assigning it to the same variable.
The code above is not very nicely formulated; write your own logic.

Question about Conceptual Understanding for Circular doubly linked list in Java

I am a beginner coder in java and in general and I wanted to ask for some help. I am doing an assignment in which I am supposed to make a CircularLinkedList which is like a DoublyLinkedList. But for CircularLinkedList am not allowed to have a head or a tail. Instead, I have a pointer to one of the nodes in the CircularLinkedList. So, to my understanding from basic LinkedList, the head node is where we would implement our series of Singly LinkedList.
I have made a DoubleNode pointer as a global variable that will at first point at the first node when we create a circular linked list. when I construct a CircularLinkedList that is empty.
My question is: Should this DoubleNode pointer point to null within the constructor or should I just create a new node and make them point to null with not value to claim its empty?
I am posting my code for better understanding my concept
public class CircularLinkedList<T> {
DoubleNode pointer; //create a double node of pointer [/| no data |\]
int lengthoflinkedlist = 0;
private class DoubleNode<T> { //create a DoubleNode class to understand how nodes would look in the circular linked list
private DoubleNode prev;
private T data;
private DoubleNode next;
// Now we input our functions into the class or methods as they call it
public DoubleNode(){ //constructors for bas node.
this.prev = null;
this.next = null;
}
public DoubleNode(T data) {
this.prev = null;
this.data = data;
this.next = null;
}
public DoubleNode(DoubleNode P, T data, DoubleNode N){
this.prev = P;
this.data = data;
this.next = N;
}
}
public CircularLinkedList() {
// pointer
DoubleNode A = new DoubleNode(); // creates a node with nothing and pointers to null;
}
public CircularLinkedList(int initSize, T initValue) { //constucting a circular linked list
// TODO implement me
//initSize means the size of linkedlist
//initValue means the value of data T in the nodes.
if(initSize == 0) { //throw error as length 0 means linkedlist is empty
System.out.println("The linked list with size 0 means it is an empty linkedlist with a Pointer pointing to Nothing");
}
else {
DoubleNode check = this.pointer;
for(int lengthoflinkedlist = 0; lengthoflinkedlist < initSize - 1; lengthoflinkedlist++) {
DoubleNode A = new DoubleNode(this.pointer.next,initValue,this.pointer.prev);
}
}
}
public void moveForward() {
// TODO implement me
}
public void moveBackward() {
// TODO implement me
}
public T getValue() {
// TODO implement me
return null;
}
/**
* #return the previous value of the updated node
*/
public T setValue(T value) {
// TODO implement me
return null;
}
public void addBefore(T value) {
// TODO implement me
}
public void addAfter(T value) {
// TODO implement me
}
/**
* #return the previous value of the removed node
*/
public T removeBefore() {
// TODO implement me
return null;
}
/**
* #return the previous value of the removed node
*/
public T removeAfter() {
// TODO implement me
return null;
}
public boolean isEmpty() {
// TODO implement me
return true;
}
}
I am still implementing my class and constructors atm so i need help based on that
My question is, first of, I have made a DoubleNode pointer as a global variable that will at first point at the first node when we create a circular linked list.
I can't see a "global" variable. I can see an instance variable called pointer ... which I assume is what you are talking about.
Should this DoubleNode pointer point to null within the constructor or should I just create a new node and make them point to null with not value to claim its empty?
Actually, you can do it either way.
One way would be to have an empty list represented as a CircularLinkedList with a null value in the pointer field.
Another way would be to have an empty list represented as a CircularLinkedList with a pointer that refers to a DoubleNode with null data.
I think that the first approach will be simpler. Either way you need special case code for when the list is empty.
You wrote:
But for CircularLinkedList am not allowed to have a head or a tail.
I would expect this to be true since a circle doesn't have a concrete beginning or end. In a circle, they are arbitrary. Unlike a conventional list, when a circular list is empty, the head (beginning node) is whatever you want it to be. The trick is how you calculate the end. This is important because at some point you need to calculate if the circular list is full.
Assume this array is your "circular list". You could literally decide to make your first insertion right in the middle (index 2). In this case, the "tail" will be your starting index minus 1 (i.e. 1). The problem is, how do you wrap around when you reach index 4 to go to index 0 for the next insertion?
To increment an index in a wrap around manner, you need to use the following formula: index = (index + 1) % N where N is the size of the list; in this case 5.
Now, how do you know your circular list is full? This is actually pretty simple. Before you insert, you will "peek" to the next location to see if there is something there already. If the next slot in your circular list is empty, you can then insert. ON the other hand, if the next slot is full, your list is full.
Last, you need to consider going in reverse order (i.e. to get previous node). The technique is the same. First, you will "peek" the previous index to see if there something there. If the previous slot has a node, you can freely do what you need with it.
The rest of things to considered are unknown to me because your post is not very specific.

Constructor Node cannot be applied to given types while working with nodes

I am working on a code that puts new elements on MyStack if they are unique. I had to copy and paste the node starting code, so I'm having a bit of trouble with an issue. I keep getting two error messages, even after trying various workarounds and I'm not really understanding why. I've even tried using some helper functions I've previously made that have worked before so I'm extra confused.
The two errors I consistently get are:
-cannot infer type arguments for MyStack.Node (actual and formal arguments differ in length)
-constructor node cannot be applied to given types. Required, no arguments, found: anything,
Here's my code:
public class MyStack<Anything>
{
private Node first, last;
private class Node<Anything>
{
Anything item;
Node next;
}
public boolean contains(Anything value)
{
for (Node curr = first; curr != null; curr = curr.next)
{
if (value.equals(curr.item)) {
return true;
}
}
return false;
}
public void add(Anything value)
//method that adds a new value to the end of the list
//COMPLETE
{
Node temp = first;
while(temp.next!=null){ //finds the end
temp=temp.next;
}
temp.next=new Node(value, null); //assigns new value
}
public void enqueue(Anything info){
if (this.contains(info)==true) { //if the info is already present
System.out.println("the stack already contains this value");
return;
}
//if we actually need to add the info
if (first == null) { //if there is nothing in the stack
Node temp= first;
first = new Node<>(info,temp);
first = temp;
return;
}
if (first != null) { //if there is already stuff
Node temp = first;
while (temp.next == null)
{ Node newNode= new Node<>(info, temp);
temp.next = newNode;
}
return;
}
}
}
As #Andreas already pointed out, Node needs a constructor.
There are a few other flaws in your Code:
Use Generics
With your Code, you can only store Objects of the class Anything, what strongly limits its reusability. Use a generic instead and you can reuse this class for many more purposes.
Linked List
I suggest, you use the paradigm of a double-linked-list. That way you do not need to find the last Node to add something to the Stack. Node now has a pointer to its previous and next element.
Use the last Object
You have the object last but never use it. To find out, whether the current object is the last one you compare the value to null. This has the effect, that storing a null value will break your List. Instead compare to the Object last, this object is unique and guarantees you, that you are at the end of the list. Both first and last are Nodes that do not contain a value and are simply used to mark the start/end of your List.
Adding elements
Using the changes above, the code in the Method enqueue(T value) becomes significantly simpler: You just check whether contains(value) and decide whether you add the value to the List or not.
All these changes applied result in following code:
public class MyStack<T extends Object> {
private Node first, last;
public MyStack() {
first = new Node(null, null, null);
last = new Node(null, null, first);
first.next = last;
}
private class Node {
T item;
Node next;
Node previous;
public Node(T item, Node next, Node previous) {
this.item = item;
this.next = next;
this.previous = previous;
}
}
public boolean contains(T value) {
for (Node curr = first.next; curr != last; curr = curr.next) {
if (value.equals(curr.item)) {
return true;
}
}
return false;
}
/**
* method that adds a new value to the end of the list
*/
public void add(T value)
{
Node secondLast = last.previous;
Node added = new Node(value, last, secondLast);
secondLast.next = added;
last.previous = added;
}
/**
* only adds value if it is not already contained by the Stack
*/
public void enqueue(T value) {
if (this.contains(value) == true) { // if the info is already present
System.out.println("the stack already contains this value");
}
else {
add(value);
}
}
public static void main(String[] args) {
MyStack<String> test = new MyStack<>();
test.add("foo");
test.add("bar");
test.add("baz");
System.out.println(test.contains("bar"));
System.out.println(test.contains("new"));
test.enqueue("baz");
test.enqueue("MyStack");
}
}
Naming
As you may have noticed, in my explanation I called this class a List. This is because it fulfills more of the characteristics of a List. A Stack usually only provides the methods push to put something at the top of the Stack and pop to remove and return the topmost Object. Optionally peek can return the topmost Object, without removing it from the Stack.
Also consider renaming the method enqueue: enqueue is used in Queues (obviously) and Queues do not forbid to add two equal Objects. So the name is misleading. I would call this method something like addIfNotContaining.
In my Opinion you should name this class to be a List and add a method get(int i) to get a specific element at a position. Naturally adding some other methods like size ect. to comply with a standard List. But I assume you already had, but did not post them because they are not related to your problem.
Multithreading
This Class is far from threadsave. But I let you figure out yourself how to make it threadsave if needed.

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

Categories

Resources