Pointers in LinkedList in Java - java

I am studying the linked lists,and I'm having a little problem understanding references and pointers in Java (and also have some questions for which I can't find answer on the internet.) Namely,I have a class LinkedList that uses class Node like this:
public class LinkedList {
public Node head;
public LinkedList(int data) {
head = new Node(data);
}
}
and this is my Node class:
public class Node {
public int data;
public Node next;
public Node(int data2) {
data = data2;
}
}
I also have method toStringLL() inside LinkedList which looks like:
public void toStringLL() {
LinkedList l=this;
while(l.head.next != null) {
System.out.print(l.head.data+"->");
l.head = l.head.next;
}
System.out.print(l.head.data);
System.out.println("");
}
I don't understand why this toStringLL() changes my head of linked list,when I am iterating through it with l.head=l.head.next? Shouldn't my head stay the same?I thought that when I write LinkedList l=this,I can freely iterate through l,without affecting this(or am I wrong?) Now when I use Node n=this.head instead of LinkedList l=this,it works,but I have difficulty figuring out why that works and the previous doesn't.. Can someone explain to me the difference between these two?

I don't understand why this toStringLL() changes my head of linked list,when I am iterating through it with l.head=l.head.next?Shouldn't my head stay the same?
When you make the assignment
LinkedList l = this;
you are not creating a new LinkedList object. You are just defining a references to the existing LinkedList object.
Therefore, l.head = l.head.next does exactly the same as this.head = this.head.next. Both change your original list.
On the other hand, when you write
Node n = this.head
you are not changing the head of your List. You are declaring a variable that initially refers to the head of your List, but when you change that variable to refer to other Nodes of your list, the head variable of your list (this.head) remains unchanged.

When you set
l.head=l.head.next;
you change your head.

Related

How can I inverse a list of elements if I can only access to an element and his next one?

I have been given a "class" called LinkedList which has only one atributte
"Node first" which refers to the first element of a list. The way to access the other ones is that class "Node" has access to an element 'x' and his following one:
public class LinkedList<T> {
private static class Node<E> {
E elem;
Node<E> next;
Node (E elem) {
this.elem = elem;
this.next = null;
}
}
private Node<T> first;
So that, I have been ordered to do a method called "reverse" from class "LinkedList" which has to reverse the list. However, the difficulty of the exercise is that I can only re-link the attributte "first", I mean I cannot create auxiliar data structures and that type of help.
I have done this in order to achieve the last element of the list, but I dont know how to continue:
public void reverse () {
Node<T> aux = first.next;
while (aux.next != null) {
first.elem = aux.elem;
aux = aux.next;
}
first.elem = aux.elem;
}
It seems quite a theoretical question to me, so you might want to check Geek for Geeks first. Most of these questions that are used in programming courses are well explained there, including coding examples.
In this case, a well-known solution is to use three pointers: a current number, the previous number , and the next number; to keep track of nodes to update reverse links.
Check here: https://www.geeksforgeeks.org/reverse-a-linked-list/

why does one method destroy my linked list while another does not?

I have seen similar questions asked, but none of the answers really address my confusion.
I'm working through some Linked List content, trying to write methods to solve leetcode-like problems. I'm working with singly-linked lists, defined as:
public class LinkedListy {
ListNode head;
LinkedListy(){};
public static class ListNode {
int val; //integer variable
ListNode next; //pointer
ListNode() {}
ListNode(int val) {
this.val = val;
}
ListNode(int val, ListNode next) {
this.val = val; this.next = next;
}
}
...
I'm trying to write a function that will reverse my linked list, but will not destroy my original linked list. The code I have written works to reverse the list, but destroys the original list:
public ListNode reverse() {
//use copyList function to avoid altering head --> DOESN'T WORK
ListNode current = head;
ListNode temp = null;
ListNode copied_result = null;
while(current != null){
temp = current.next;
current.next = copied_result;
copied_result = current;
current = temp;
}
return copied_result;
}
From reading on here and other places, I understand that by setting current = head, I'm just creating a new reference for the same ListNode. Thus, when I run my code, I'm mutating the original list.
Main Confusion: I'm confused because I have written methods that do NOT destroy the original list, but use the same kind of reference to head. For example, in my "length()" method, I set dummy = head and alter dummy to find the length of the list. But, then the original list doesn't get changed (I wrote a print function to print the list and I verified it prints the same before and after calling length().)
public int length() {
ListNode dummy = head;
int length = 0;
while(dummy != null) {
dummy = dummy.next;
length++;
}
return length;
}
So, I'm clearly not understanding something fundamental about LinkedLists.
Why does my reverse() method destroy the original list when my length() method does not?
Is the only way to write a reverse method for a linked list without destroying the original list to make a copy of the original list in your main method and reverse the copy?
Any help or resources would be greatly appreciated. Thanks!
In the length method, you're using a locally accessible variable named dummy to iterate through the nodes in the list; when you set dummy = dummy.next, this sets the value of the local variable to refer to the next node. This is very different from doing something like dummy.next = null, which would affect the content of node to which dummy currently refers.
To that end, your reverse method doesn't actually 'destroy' the original list - the main issue is that head isn't being set to the first element when you're finished. Thus, head still 'points' to the same node it did before the function started, which is now the last node.
If you want to reverse the list in-place, then just updating head properly at the end of your function will work fine - if you want to return a reversed copy of your original list without modifying the original, you'll need to copy all of the nodes. See #Hank_interprize's description of deep/shallow copies.
I believe the issue here is you are not actually copying any new information over to the new list but instead the code is just using the same list as before under a new name. This can be done with a deep copy.
To create a new list you will need to copy the old data over to a new list with a whole new system of pointers and simply copying the data over to the new linked list which is different than copying the pointer.

Why to have a parent class for linked list

This is a general question, maybe about OOP concept. I am just starting with DS implementation in JAVA.
I am trying to implement Linked List and on all online rsources, I see a similar practice:
Make a node class.
Make a class Linked List that has a node object.
Similarly I saw for stack, queues and trees. My question is, if I implement LinkedList by only having one class that looks like below:
class LinkList {
int data;
LinkList next; }
I am still able to do all the operations. So the concept of having a second class that contains a root or a header is only for OOP purpose or something else?
I wrote the following code and it works all well without the need to have a header pointer. I use a references variable in all the methods and the main class's object still keeps the track of the head.
/* package codechef; // don't place package name! */
import java.util.*;
import java.lang.*;
import java.io.*;
class LinkList {
int data;
LinkList next;
LinkList(){
data = 0;
next = null;
}
LinkList(int data) {
this.data = data;
next = null;
}
LinkList insertAtBegin(int data){
LinkList newBegin = new LinkList(data);
newBegin.next = this;
return newBegin;
}
void insertAtPlace(int data, int insertData){
LinkList newNode = new LinkList(insertData);
LinkList iterator = this;
while(iterator!=null && iterator.data!=data){
iterator = iterator.next;
}
if(iterator.data == data)
{
newNode.next = iterator.next;
iterator.next = newNode;
}
}
void insertAtLast(int data) {
if(next == null){
next = new LinkList(data);
}
else{
next.insertAtLast(data);
}
}
}
/* Name of the class has to be "Main" only if the class is public. */
class Codechef
{
public static void main (String[] args) throws java.lang.Exception
{
// your code goes here
LinkList linkList = new LinkList(6);
linkList.insertAtLast(5);
linkList.insertAtLast(3);
linkList.insertAtLast(2);
linkList.insertAtLast(1);
linkList = linkList.insertAtBegin(10);
LinkList iterator = linkList;
while(iterator!=null){
System.out.print(iterator.data);
iterator = iterator.next;
}
System.out.print("\n");
linkList.insertAtPlace(5,-1);
iterator = linkList;
while(iterator!=null){
System.out.print(iterator.data);
iterator = iterator.next;
}
}
}
You must keep track of the head of the linked list somewhere. Otherwise, how would you iterate over the entire list, or search for an element in the list?
If your LinkList is essentially a node (with data and reference to the next node), you would have to implement all the linked list operations (add, delete, etc...) in some separate class that keeps track of the head node of the list.
This brings you back to a linked list class that uses a node class.
As for the code you added, LinkList insertAtBegin(int data) will only insert a node at the beginning of the list if you call it on the first node of the list. But there's nothing stopping you from calling it on any node of the list, in which case it will essentially return a new list that starts with the new elements and ends with a sub-list of the original list.
There are several reasons to have two classes:
to distinguish the notion of a list and that of a single node,
to avoid the awkward returning of the head node from each method,
to avoid letting the client of the class have the responsibility to keep track of the head node,
to hide the implementation details, so that the class could be more easily replaced with an equivalent one,
etc...
Your LinkList class would just be a node class in the first example, because it holds the data and the node that comes after it
The general purpose of having a LinkedList class is to have a "wrapper" for the list, it's just a class that holds the head of the list (which in the case of a linked list, is the list) and perhaps some functionalities such as a find function or anything else you'd need.
so in your case (2nd example) it is just a wrapper class that implements some extra functionalities (insertAtBegin(), insertAtPlace() and insertAtLast())

Optimal ways to Traverse through a LinkedList - Java

The Situation
I have a interview with TripAdvisor tomorrow and I decided for practice to create my own custom LinkedList. I'm trying to figure out the best way to traverse through it.
Primary Question: I have managed to traverse through my Linked List however I believe
there is a better way to do it. How would you traverse through it ?
Bonus Question: How do my overall classes look ? Is there anything I should/should not add ?
It seems to work fine but is it optimal ?
Bonus Question #2: Lastly I was wondering if anyonehad any insight to typical interview questions/concepts that I must know ?
Greatly appreciated.
Here are my Classes
// *********************************Node Class*******************************************
public class Node<T> {
Node<T> link;
T data;
public Node(T data) {
this.data = data;
link = null;
}
public T getData() {
return data;
}
public Node<T> getLink() {
return link;
}
public Node<T> setLink(Node<T> N) {
this.link = N;
return link;
}
public void setData(T newData) {
this.data = newData;
}
}
//****************************************Linked List Class*******************************
public class LinkedList<T> {
Node<T> head;
T data;
public LinkedList(){
head = null;
}
public void add(T data){
Node<T> newNode = new Node<T> (data);
newNode.setLink(head);
head = newNode;
}
//had problems printing out the data in the last node
public void traverse(){
Node<T> pointer;
pointer = head;
while (pointer.getLink()!=null){
System.out.println(pointer.getData());
pointer = pointer.setLink(pointer.getLink());
}
//Fixed problems For last node that doesnt get printed out
System.out.println(pointer.getData());
}
//Again is there a better way to do this ?
//Thanks
}
I would change your traverse function to be more like this:
public void traverse(){
Node<T> pointer = head;
while (pointer != null){
System.out.println(pointer.getData());
pointer = pointer.getLink();
}
}
Also it is common to represent the Node class as a private inner class of LinkedList because it is not typically needed anywhere else.
As far as the interview itself goes, traversal questions are more typical for binary-trees (eg. print out the elements in sorted order). LinkedList questions are more focussed on the remove/insert operations which both require careful attention to the edge cases (what happens when you remove the head for example). A more advanced LinkedList question would ask how to detect a cycle, I would make sure that I knew at least one method of doing this (have a look at the Tortoise and the Hare algorithm).
EDIT:
Algorithm questions will nearly always be from the following list:
String manipulation such as:
Reverse String
Count how many times each letter appears in a given String (use a Map for this)
LinkedList questions such as:
How to remove a node, pay close attention to edge cases such as removing the head
How to reverse a linkedList (make the Tail the Head)
Binary Tree questions such as:
In-order traversal
If there is a BTree balancing question you won't need to implement it, just understand that a completely unbalanced Binary Tree is simply a Linked List.
Understand that searching a balanced Binary Tree is O(log n) compared to a Linked List or a completely unbalanced Binary Tree which is O(n).
You will probably be asked to describe the complexity of the solution you just gave (big-O notation)
See this and this for questions related to Java itself

Building Singly LinkedList

I am attempting to build a data structure in Java with inner list that are made up of singly link lists that contain integers. I am having trouble with the architecture of my data structure. It needs to have a inner class with functions that can merge, split, and give the size of the inner lists.
Assume that the size of the inner lists will change and size and data will be removed to consolidate and optimize the data structure.
I have a driver class to interface with the data structure. Then I have a Data structure class which will have the inner class.
Where do I put methods to add/remove top level lists as the singly linked list collapses and expands with my data??
How many classes should I have? A driver, the data structure(with inner class)... more?
I just need a little direction from someone who is a strong coder, I made multiple attempts at top down designs, and I have read and searched. I just need some direction. I attached and image of how the data structure looks.
PLEASE NOTE:
The inner lists must be implemented as a singly-linked lists with dummy headers and tail pointers, and I must not use any data structures from Java Collections API for the inner lists. For the top-level list, I have to use the generic LinkedList class from the Java Collections API.
Note: This looks like a homework, otherwise there would be no need to reinvent the wheel. Knowing this, I won't provide specific code, just pseudocode (except for some keywords like class, int and similar), no useful methods like getters or setters, no additional fields, etc. It will be your job to generate all the necessary Java code to make this work.
I don't know where to start, I am new to linked lists
Start by defining the structure of the elements that will go inside the list. How to do this? Review the requirement (emphasys mine):
build a data structure in Java with inner list that are made up of singly link lists that contain integers
You need a data structure that at first can hold an integer value and behaves as singly linked list. From the definition of singly linked list, the structure contains two elements:
The integer data to hold
The pointer to the next similar data structure.
This can be addressed like this:
class DataStructure {
int data;
DataStructure next;
}
Now that you have the structure that supports the singly linked list, you need a new structure that will be the singly linked list and define the behavior of it. This can be addressed as stated in your requirements:
The inner lists must be implemented as a singly-linked lists with dummy header and tail pointers
Moving this into pseudocode:
class SinglyLinkedList {
DataStructure head;
DataStructure tail;
}
That's it. Now that you have your SinglyLinkedList, you just need to define the behavior. Again, reviewing the requirements:
It needs to have a inner class with f̶u̶n̶c̶t̶i̶o̶n̶s̶ methods that can merge, split, and give the size of the inner lists.
From here, we can define at least three methods for the SinglyLinkedList data structure: merge, split and size. Adapting the latest class from it:
class SinglyLinkedList {
DataStructure head;
DataStructure tail;
//added this method just to know you need to add data to your singly linked list
public void add(int data) {
}
//you merge a list with another list
public void merge(SinglyLinkedList singlyLinkedList) {
}
//you split the list into two or more lists
public SinglyLinkedList[] split() {
}
//the size of the list is a numeric positive value
public int size() {
}
}
EDIT (based on your edit and by looking at the picture)
There's the need to define another data structure that holds a list of singly linked lists. By requirements:
For the top-level list, I have to use the generic LinkedList class from the Java Collections API.
Then, you just need a new structure that uses a LinkedList that will contain your singly linked lists:
class SinglyLinkedListHolder {
LinkedList<SinglyLinkedList> holder;
public SinglyLinkedListHolder () {
holder <- new LinkedList<SinglyLinkedList>();
}
//this holder should at least add new singlyLinkedList in the bigger list
public void add(SinglyLinkedList singlyLinkedList) {
}
}
Note: I notice that you tried to define your structure with generics:
private static class Node<T> {
}
I highly recommend you to not do this until you really grasp the main concepts about how a singly linked list works. It can take some time, but it is better to go step by step. After making this structure to work, then you can easily (in fact, depending on your implementation) replace the structure to:
class DataStructure<T> {
T data;
DataStructure next;
}
public class LL {
class Node
{
String data;
Node next;
Node(String data)
{
this.data=data;
this.next=null;
}
}
public Node head;
public void add_first(String data)
{
Node NewNode=new Node(data);
if(head == null)
{
head=NewNode;
return;
}
NewNode.next=head;
head=NewNode;
}
public void add_last(String data)
{
Node NewNode=new Node(data);
if(head==null)
{
head=NewNode;
return;
}
Node currentNode =head;
while(currentNode.next !=null)
{
currentNode=currentNode.next;
}
currentNode.next=NewNode;
}
public void insert_pos(String data,int pos)
{
Node NewNode=new Node(data);
Node current=head;
for(int i=0;i<pos-1;i++)
{
System.out.println("Current is"+current.data);
current=current.next;
}
System.out.println(current.data);
NewNode.next=current.next;
current.next=NewNode;
System.out.println("Delete Element Successfuly at position"+pos);
}
int counter;
public void size()
{
Node current=head;
if(head==null)
{
System.out.println("Linked list is Empty.......");
}
while(current!=null)
{
current=current.next;
counter+=1;
}
System.out.println("Linked list size is:"+counter);
}
public void display()
{
Node cur=head;
while(cur!=null)
{
System.out.print(cur.data+"->");
cur=cur.next;
}
System.out.println("null");
}
public void delete_first()
{
Node temp=head;
head=temp.next;
System.out.println("Delete First Element Successfuly");
}
public void delete_last()
{
Node current=head;
Node lastnode=head.next;
while(lastnode.next!=null)
{
current=current.next;
lastnode=lastnode.next;
}
current.next=null;
System.out.println("Delete last Element.");
}
public void delete_pos(int pos)
{
Node current=head;
Node last=head.next;
for(int i=0;i<pos-1;i++)
{
System.out.println("Current is"+current.data);
current=current.next;
last=last.next;
}
current.next=last.next;
}
public static void main(String[] args)
{
LL list=new LL();
list.add_last("A");
list.add_last("B");
list.add_last("C");
list.add_last("d");
list.add_last("e");
// list.delete_pos(3);
//list.delete_first();
//list.delete_last();
// list.insert_pos("nirav",4);
list.size();
list.display();
}
}

Categories