Understanding setup for doubly linked list in Java - 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.

Related

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.

Storing One String Value in an empty LinkedList

public class LinkedListExplained {
public Node head;
public Node tail;
public int size;
public LinkedListExplained() { // Constructor
head = null;
tail = null;
size = 0;
}
public class Node{ // Inner Class
String value;
Node next;
}
public void add(String value){
Node node = new Node();
node.value = value;
size++;
if (head == null){
head = node;
tail = node;
return;
}
tail.next = node;
tail = node;
}
Question, when storing a single String value to an empty LinkedList, does it store the same value twice?
Once as head and once as tail?
No. The head and tail variables point to the same Node object. That object contains the String once.
If you are learning Java, the first and foremost thing you need to understand is that in Java, everything that looks like an object is never actually an object; it is a pointer to an object. And of course two pointers may point to the same object.
So, the statement public Node head; does not declare an instance of Node. It declares a pointer to an instance of Node. That's why you have to use new Node(); later.
So, since you set both the head and the tail pointers to point to the same instance of Node, it might appear that you have two copies of that node, but in fact you do not. You only have one instance of Node, and you have two pointers pointing at it.

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.

understanding some concepts in java generics

So I came across this code while studying linkedlists. The code here uses generics and I am having problem understanding some of the things here.
public static class Node<E>
{
E element;
Node <E> next;
public Node(E e,Node <E> n)
{
element=e;
next=n;System.out.println(next);
}
public E getelement() {return element;}
public Node<E> getnext(){ return next;}
public void setnext(Node <E> n)
{
next=n;
}
}
So what does class Node <E> mean?
I think E element; means element is of type E. Am I right?
Node <E> next; what does this mean?
The <E> by the class name declares that E as a generic type parameter - this means any instance of Node will be of some type, and this type will be decided by the code that instantiates it. new Node<String>() will create a node of type String, new Node<Integer>() creates a node of type Integer, and so on.
Where E is used in the class then reflects whatever type a particular instance has chosen, so if a have a node of type String, I know that element will be a String, and next will be a reference to another node containing a String.
The beauty of generics is that using this type parameter means I don't need to write a copy of this class for each type I want to use, while also being sure that all of the references will be of the type I expect - I won't get next returning an Integer when I'm expecting a String.
The link JB Nizet provides is a very good one - generics are quite a large and subtle topic, and if you wnat to learn about generics that tutorial will help you a lot.
I always learn best from example, so put Node to a simple use:
import java.awt.Point;
public class TestNode{
public static void main(String[] args) {
//assume you have 3 points
Point point1 = new Point(40,40);
Point point2 = new Point(80,120);
Point point3 = new Point(70,200);
//each point is connected to one other point. to represent such connection you
//can create a Node<Point> or in other words Node of Point.
//define the last node in the chain, which has no next node:
Node<Point> node3 = new Node<>(point3, null);
//Note: because Node<E> is generic you could define Node<Cats>, Node<Dogs>, Node<AnyType>
//define the point2-point3 connection
Node<Point> node2 = new Node<>(point2, node3);
//define point1-point2 connection
Node<Point> node1 = new Node<>(point1, node2);
//now put it to test. node1.getnext() return node2, node1.getnext().getelement() returns point2
System.out.println("Point 2 x-y " +node1.getnext().getelement().getX()
+"-"+node1.getnext().getelement().getY());
//now put it to test. node1.getnext().getnext() return node3
System.out.println("Point 3 x-y " +node1.getnext().getnext().getelement().getX()
+"-"+node1.getnext().getnext().getelement().getY());
}
}
You can easily find official docs and many other resources for such a big topic in Java, I'll try to explain it by "the process of re-creating generics".
Say you're going to implement the class Node given in the question, it's a basic building unit for LinkedList, so you define it as:
class Node {
private Node next;
public Node getNext() {
return next;
}
public void setNext(Node n) {
next = n;
}
}
but you need to store some data in each Node, don't you, otherwise this class is useless. Obviously one more field is necessary and the type you want to store is MyData, then it'll be:
class Node {
private MyData element;
private Node next;
public Node getNext() {
return next;
}
public MyData getElement() {
return element;
}
public void setElement(MyData element) {
this.element = element;
}
public void setNext(Node n) {
next = n;
}
}
One day you want to make your implementation a common library so it can be used by anyone, but one serious problem comes up which is people will not happy with that they can only store data of type MyData in your Node, they want to store whatever type they want, so you made a little change - declare the type of element to Object so that it can handle any type:
class Node {
private Object element;
private Node next;
public Node getNext() {
return next;
}
public Object getElement() {
return element;
}
public void setElement(Object element) {
this.element = element;
}
public void setNext(Node n) {
next = n;
}
}
Everything's good now, but some time later you receive some feedbacks from some picky users:
User A: everywhere I call Node.getElement() in my code, I get an Object type stuff and I need to do a type cast, which is inconvenient, it would be better if what I get from getElement is the type I want
User B: I want to only store type A but there's no way to prevent me put a type B into Node, I can't find this bug till exception happens during runtime, it would be better that compiler can help me to find the bug
So you feel that it'll be great if you can leave the decision of what type of data is allowed to put in Node to users, rather than hardcoded in implementation, which means what you'll put at the underscore of the statement private ___ element; is uncertain, you need it be a variable and specified by the user at the moment they use it, so a variable to the class, that's good, but you need a place to declare the variable before you can use it, finally you decide to put the declaration of the variable right after the class name, inside <>(a new syntax), then the code will be:
class Node<E> {
private E element;
private Node next;
public E getElement() {
return element;
}
public void setElement(E element) {
this.element = element;
}
public Node getNext() {
return next;
}
public void setNext(Node n) {
next = n;
}
}
almost done but wait: you're using Node by yourself - the field next, you need to follow the rule you just made: pass type info of element to Node at the time when you use it, so finally you got the code following:
class Node<E> {
private E element;
private Node<E> next;
public E getElement() {
return element;
}
public void setElement(E element) {
this.element = element;
}
public Node<E> getNext() {
return next;
}
public void setNext(Node<E> n) {
next = n;
}
}
Em....Sorry I didn't expect this to be so long...But hope it could be a little helpful to you.

Making first object with a recursive class defination [duplicate]

This question already has answers here:
Java final modifier
(2 answers)
Closed 8 years ago.
I was experimenting a bit in java and stumbled across this problem
Suppose i have a class with this recursive defination
public class Node<T> implements Iterable<T>{
public final T element;
public final Node<T> next;
public Node(T head, Node<T> tail) {
this.element = head;
this.next = tail;
}
// Contains few more methods and implementation of iteratable like add, remove etc
}
Now, the thing is I will be using this class as a field in another class with final keyword. Now if in the beginning i would be making an empty list and then add it to the list, how should i proceed.
TO make it simple
class NodeList <T>{
private final Node<T> head;
public NodeList(){
}
// Few more functions
}
Using NodeList class how can i create an empty list and later on add data using add function
In java reference works as pointer to an object in memory that internally can point to another one in the same way.
Let's try to understand it visually:
What happens to the pointer head when the object obj is added to an empty linked list?
You have to remove final keyword from head because it's reference that changes every time when new node is added to point the new node.
In below snapshot head is a reference that point to first object in the memory and first object contains another reference next that points to second object and so on...
how should i proceed.
create a new node
point next of new node to next of head
point head to new node
Sample code:
class Node<T> {
public final T element;
public final Node<T> next;
public Node(T head, Node<T> tail) {
this.element = head;
this.next = tail;
}
}
class NodeList<T> {
private Node<T> head;
public void add(T value) {
if (head != null) {
Node<T> node = new Node<T>(value, head); // create a new node
head = node; // point `head` to new node
} else {
// if head is null then assign it to head
head = new Node<T>(value, null);
}
}
}
NodeList<String> nodeList = new NodeList<String>();
nodeList.add("First");
nodeList.add("Second");
nodeList.add("Third");
// print all nodes
Node<String> node = nodeList.head;
while (node != null) {
System.out.println(node.element);
node = node.next;
}
output:
Third
Second
First
You cannot do it with the final keyword on the head attribute, since it will force you to initialize it during the instanciation : you should then initalize it to null to represent the empty list and won't be able to append an element to it. Remove the final keyword, it has no use there.
I'm not even convinced of the use of final in your Node class. What if you want to add or remove an element in the middle of the list ? Using final there limits considerably the number of operations you can perform on your data structure.

Categories

Resources