Object is getting updated without that object reference? - java

//I have a Node.java Class
public class Node{
int data;
Node next;
public Node(int d) {
data = d;
}
}
//And another java class
class LinkedList {
Node head;
public static void main(String[] args) {
LinkedList list = new LinkedList();
//Executing this loop
for (int i = 0; i < 5; i++) {
**list.add(i);**
}
}
void add(int value){
Node newNode = new Node(value);
if(head == null )//Very first time its create the head object when i = 0
{
head = newNode;
}else if(head.next == null){//This is for when i value is 1
head.next = newNode;
}else{ //else part execute i >= 2
//Created new node with head.next which mean value 1.And head is 0
Node temp = head.next;
// Just need this object initialization for reference
Node temp1 = newNode;
//Checking head.next is null or not if its null skip this loop execution
while(temp != null)
{
temp1 = temp;
temp = temp.next;
}
// Here we set newNode.next to null
newNode.next = temp1.next;
temp1.next = newNode;
}
}
}
My Question is here , when temp1.next = newNode; line execute head object have added
one next value.
**
//For example if head = 0,head.next = 1 when temp1.next = newNode; line execute head.next.next = 2 is getting added with head. How its happening when we do not have head object reference.

You are not updating the head object.
You are updating the head.next object.
So
head.next.next
can be written like this:
Node nextFromHead = head.next; // nextFromHead is 1
Node nextFromNextFromHead = nextFromHead.next; // nextFromNextFromHead is 2
head.next.next is the same object as nextFromNextFromHead but it ( the Node that is 2 ) doesn't have any direct connection to the head node.
I think this will help better understand how references work in java.
public class LinkedList {
static Node head;
public static void main(String[] args) {
LinkedList list = new LinkedList();
for(int i = 0; i < 5; i++)
list.add(i);
Node currentNode = head; // in java we don't need object initialization for reference. Node temp1; would work just fine
System.out.println("==head node== " + currentNode);
while(currentNode.next != null) {
// here we increment
currentNode = currentNode.next;
// System.out.println("Last time we in here, next is null so print only current");
System.out.println("==next node== " + currentNode);
}
}
void add(int value){
Node newNode = new Node(value);
if(head == null )//Very first time its create the head object when i = 0
{
head = newNode;
}else if(head.next == null){//This is for when i value is 1
head.next = newNode;
}else{ //else part execute i >= 2
//Created new node with head.next which mean value 1.And head is 0
Node temp = head.next;
// Just need this object initialization for reference
Node temp1 = newNode;
//Checking head.next is null or not if its null skip this loop execution
while(temp != null)
{
temp1 = temp;
temp = temp.next;
}
// Here we set newNode.next to null
System.out.println(" ==temp1== " + temp1);// before
newNode.next = temp1.next;
temp1.next = newNode;
System.out.println(" ==temp1== " + temp1);// and after
}
System.out.println("==current node== " + head);
System.out.println();
}
}
And the Node class with an additional toString() for properly viewing the objects.
public class Node {
int data;
Node next;
public Node(int d) {
data = d;
}
#Override
public String toString() {
return "Node{" +
"data=" + data +
", next=" + next +
'}';
}
}

"You" do have the head element.
Have a look at your code: your LinkedList class has a field head; and whenever you call the add() method of your list; that field is accessible by that method.
So, adding works like this:
If the head is not set, a new one is created
If the head is set, but has no "next", then that next node is created and linked to head
If the head is set, and his "next", then you keep retrieving the "next" next ... until you find one the last one; which doesn't have a next (yet) ...
That is all there is to understand. Or lets try some non IT-example.
Assume you some hook and short ropes; and you want to build a "list of ropes".
No list yet. You take the first rope and attach it to the hook.
The first rope, your head, is there. You add another rope, by connecting it to the end of the first one (probably making a knot)
Adding another rope ... you start at the hook, and you keep following the ropes/knots ... until you have a loose end.
Hope that helps.

Related

How to delete tail in Double Link List?

My teacher guides us in this activity on how to delete the tail of the double link list. He created an step by step process or algorithm for us to follow. I followed it, but it doesn't work. Or maybe I am following it wrong. Here is the algorithm
Check if the list is empty
If not Empty
Check if there is only one node in the list
If only one node, set the head and tail reference to null.
if more than one node
create a temptail to point to next tail (tail.prev)
set the prev of the tail and next of temptail to null
assign the temptail value to the tail
Here is my code
public void delTail(){
DoubleNode temp;
if(isEmpty()){
return;
}
else if(!isEmpty()){
if(head == tail){
head = tail = null;
}
else{
temp = tail.next;
tail.prev = null;
temp.next = null;
temp = tail;
}
}
}
This is the error that i saw error in my terminal
I think that I am following it right or maybe not? Thank you so much for your help :)
This is my constructor*
public class DoubleNode{
public DoubleNode prev;
public int data;
public DoubleNode next;
public DoubleNode(int d){
this(null, d, null);
}
public DoubleNode(DoubleNode p, int d, DoubleNode n){
prev = p;
data = d;
next = n;
}
}
this is mt entire operator code*
public class operator{
DoubleNode head;
DoubleNode tail;
DoubleNode laman;
String output = "";
public operator(){
head = tail = null;
}
public boolean isEmpty(){
return head == null;
}
public void addHead(int i){
if(isEmpty()){
head = tail =new DoubleNode(i);
}
else{
head = new DoubleNode(null, i, head);
head.prev = head;
}
}
public void addTail(int i){
DoubleNode last = new DoubleNode(i);
if(isEmpty()){
head = tail = new DoubleNode(i);
}
else{
tail.next = last;
tail = last;
}
}
public void delHead(){
DoubleNode temp = head.next;
if(head==tail){ //this if condition is testing if the head and tail is one only,
head = tail =null; //if there is only one this will set the tail and head to null
}
else{
head = head.next;
head = temp;
}
}
public void delTail(){
DoubleNode temp;
if(isEmpty()) {
return;
}
else {
if(head != tail) {
tail = tail.prev;
temp = tail;
}
else {
head = tail = null;
}
}
}
public void display(){
DoubleNode tmp = head;
output = "<html>";
for(tmp = head; tmp != null; tmp = tmp.next){
output = output + "<br>" + tmp.data + "<b>" + "<br>";
}
output = output + "</html>";
}
}
This is my entire code so far, i have a main class with a jframe but i think its fine because i also use it for single link list. But I do have a problem here at double link list regarding on deleting the last node
Your problem is that you're just assigning to temp but don't actually use it. Additionally you're not setting the link back to the previous element correctly.
Assuming tail.next points to head again you might do the following:
tail.prev.next = tail.next; //you might need to check for `tail.prev` being null
tail.next.prev = tail.prev; //you might need to check for `tail.next` being null
//delete tail
To illustrate:
A -next-> Tail -next-> Head
^---prev--+ ^---prev--+
Step 1:
+----next--------------V
A Tail -next-> Head
^---prev--+ ^---prev--+
Step 2:
+----next--------------V
A Tail -next-> Head
^---prev--+ |
^--------------prev----+
Actually if tail.next == head removing the tail is no different than removing any other node.
You have two errors in your else block:
You never change the tail reference. The last statement should really be an assignment to tail.
You seem to assume that the tail has a non-null next reference, but that is a contradiction. The tail is supposed to be the last node, so its next reference will always be null (unless you are supposed to create a circular list). By consequence, temp will be null, and the statement temp.next = tail will trigger the Null Pointer Exception.
The more interesting property of tail is its prev property, which refers to the node that will become the tail after the current tail node has been removed. This tail.prev is explicitly mentioned in your assignment.
So:
else {
temp = tail.prev; // <--- should point to the new tail
tail.prev = null;
temp.next = tail;
tail = temp; // <--- reverse the assignment
}
Several other issues...
In addHead you do not set the prev property correctly. You make it a self-reference. Realise that head is already referencing the new node. Change:
head.prev = head;
to:
head.next.prev = head;
In addTail the assignment to prev is missing. Change:
tail.next = last;
tail = last;
to:
tail.next = last;
last.prev = tail; // needed!
tail = last;
In delHead you must make sure the new head's prev is null. So change:
head = temp;
to:
head = head.next;
head.prev = null;
NB: you don't need DoubleNode temp = head.next; in that method.

Create a loop in a Java LinkedListArray and make the method detectLoop return true

Am having a lot of trouble creating node to complete a loop in this SinglyLinkedList after i checked whether it contains a loop with this method here detectLoop, The first call of this method returns an expected false because i created a SinglyLinkedList without a loop...So after printing out that boolean value, i tried to create a Node to loop the List but its still returning false, and then it says non-static member Node cannot be referenced from a static reference
class SinglyLinkedList {
class Node {
int data;
Node next;
public Node(int data) {
this.data = data;
this.next = null;
}
}
//Represent the head and tail of the singly linked list
public Node head = null;
public Node tail = null;
//addNode() will add a new node to the list
public void addNode(int data) {
//Create a new node
Node newNode = new Node(data);
//Checks if the list is empty
if (head == null) {
//If list is empty, both head and tail will point to new node
head = newNode;
tail = newNode;
} else {
//newNode will be added after tail such that tail's next will point to newNode
tail.next = newNode;
//newNode will become new tail of the list
tail = newNode;
}
}
//display() will display all the nodes present in the list
public void display() {
//Node current will point to head
Node current = head;
if (head == null) {
System.out.println("List is empty");
return;
}
System.out.println("Nodes of singly linked list: ");
while (current != null) {
//Prints each node by incrementing pointer
System.out.print(current.data + " ");
current = current.next;
}
System.out.println();
}
//detectLoop method to check if the loop contains a loop and return boolean
public boolean detectLoop() {
Node fastPtr = head;
Node slowPtr = head;
while (fastPtr != null && fastPtr.next != null) {
fastPtr = fastPtr.next.next;
slowPtr = slowPtr.next;
if (slowPtr == fastPtr) {
return true;
}
}
return false;
}
public static void main(String[] args) {
SinglyLinkedList u = new SinglyLinkedList();
u.addNode(7);
u.addNode(6);
u.addNode(4);
u.display();
//First Check return false as expected
System.out.println("Does a loop exist in this linked list?" + " " + u.detectLoop());
//Link a last noe to first node so that a loop is formed and check with method
//This instantiation returns an error, please help
Node loopNode = new Node(7);
//The line above throws a non-static to static reference error so i cant create a loop
u.display();
System.out.println("Does it now contain a loop?" + u.detectLoop());
}
}

Can an object like node update itself without any need of giving it an updated value?

(In the insert method): In the else statement, I don't understand how "front.next" is getting updated with the line: "prev.next = newNode". Theoretically, I understand it, but practically, although "prev" gets its value from "curr", which got its value from "front" itself, there is no way that front is getting updated because "prev". How are they talking to each other?
(Insert method)I have tried debugging and when it reaches the else statement that executes => prev.next = newNode; front.next gets updated as well which I just don't understand since front is nowhere being initialised again. Front is an object of itself.
public class SinglyLinkedList<T>
{
// inner class being created:
protected class Node<T extends Comparable<T>>
{
T val;
Node<T> next;
Node(T val)
{
this.val = val;
this.next = null;
}
Node(T val, Node n)
{
this.val = val;
this.next = n;
}
}
private Node front, tail;
public SinglyLinkedList()
{
this.front = this.tail = null;
}
// print method:
public void print()
{
// print the contents of the list
Node curr = front;
while (curr != null)
{
System.out.println(curr.val + " ");
curr = curr.next;
}
}
// insert method:
public void insert(T val)
{
Node newNode = new Node((Comparable) val);
// make a new node
if (front == null)
{
// empty list
front = tail = newNode;
}
else
{
// list is not empty
Node curr = front, prev = null;
// look for insert point.
while (curr != null && curr.val.compareTo(val) < 0)
{
prev = curr;
curr = curr.next;
}
// insert node before curr
newNode.next = curr;
if (curr == front)
{
// update front
front = newNode;
}
else
{
// update node before
prev.next = newNode;
}
if (tail.next != null)
{
// move tail to last node
tail = tail.next;
}
}
}
}
I expected curr to keep continuing to fill in the chain of nodes using curr.next and using "prev" as a temporary node used in the process of adding a node in between two nodes.
I also didn't expect print method to work since it begins with front node. Theoretically, it does make sense to start with front node, but looking at my code how "front" is not equalling to any value, but rather "curr" equalling "front", makes me feel that "front" shouldn't be having the access to the rest chain of nodes.
I expected "front.next" to be null, but it isn't.
Well, according to your code, the front works as the first node of the linked list, it actually equals to a certain value (a real node) because your code set it to be so a
if (front == null)
{
// empty list
front = tail = newNode;
}
and
if (curr == front)
{
// update front
front = newNode;
}
See! You indeed pointed it to a certain node with a given value.
For the update question. I think possibly you are always inserting a new node right next to the front node. Under that circumstance, the prev points to the same node as the front do. So if you update prev, you are updating front, too!

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!

How do I change a singly-linked list to a doubly-linked list?

I'm currently taking a Java class and the professor told us that a good practice to understand links would be to make a doubly linked list. I have made a singly linked list but I am having trouble converting it to a doubly linked list. So I was wondering if anybody could give me any suggestions on making sure my last number is connected to the previous one? And if the front number and last number connected to the null. Here is part of the code, if you wish for more of it just ask and I shall post.
The code for adding elements and such. This is my attempt of trying to make the tail which is the end connect to the last number.
public void add(int element){
Node n = new Node();
n.setItem(element);
n.setNext(head);
head = n;
>
//The tail connected to the new number added.
n.setItem(element);
n.setBefore(tail);
tail = n;
The code below is the insert function which I need to make sure the new inserted blocks connect but I'm having troubles thinking of a way to make it connect for both.
public void insert(int element, int position){
int currentposition = 0;
Node currentNode = head;
//Traverse to the right position
while(currentposition < position-1){
currentposition++;
}
Node n = new Node();
n.setItem(element);
n.setNext(currentNode.getNext());
currentNode.setNext(n);
//The previous number connecting to the new number
currentNode = tail;
}
You add an extra Node field to each Node that holds its previous Node
Insertion Pseudocode:
insert(Node n, index i) {
currentIndex = 0
currentNode = head
while (currentIndex < i) {
currentNode = currentNode.next
currentIndex++
}
n.prev = currentNode
n.next = currentNode.next
currentNode.next = n
}
For doubly linked list, you need to add both head and tail fields in the class so that it maintains a doubly linked data structure.
private Node<T> head = null;
private Node<T> tail = head;
private int size = 0;
To add a new node to the end of the linked list, you can do
public void add(T element) {
Node<T> node = new Node<T>(element);
Node<T> current = head;
if(current == null) {
current = node;
head = tail = current;
} else {
tail.next = node;
node.prev = tail;
tail = node;
}
size++;
}
Note that you also need to deal with the empty list case which is the first if clause. Also you can set next and prev references for tail when you add the node.
To insert a node to the list at a certain position, you need to consider that if the specified position is less than 0 or great than the existing list size, then error occurs because you can't insert element with out of bound index. So you can throw exception. Also you need to separate the case when the inserted position is at 0 (head) or at size (tail). Considering all these cases, the solution is:
public void insert(T a, int position) {
if (position < 0 || position > size)
throw new IndexOutOfBoundsException();
Node<T> node = new Node<T>(a);
Node<T> temp;
if(position == 0) {
if(head == null)
add(a);
else {
temp = head;
head = node;
node.next = temp;
temp.prev = node;
}
return;
} else if (position == size) {
temp = tail;
tail = node;
temp.next = tail;
tail.prev = temp;
return;
}
Node<T> current = head;
int i = 0;
while (current != null && i < position-1) {
current = current.next;
i++;
}
temp = current.next;
current.next = node;
node.prev = current;
node.next = temp;
temp.prev = node;
}

Categories

Resources