Why to have a parent class for linked list - java

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())

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/

How to implement an iterator for a custom doubly linked list implementation?

I'm implementing a custom doubly linked list in Java and I don't know exactly how to implement an iterator for it so that it can for example be easily iterated using a foreach (enhanced for) loop.
I basically want to be able to get the next or previous element with something like the code below, where it starts from a given Node and then continues to get the "next" (or "previous") element in the node variable. I want it to stop once "next" is null (which obviously will be handled by "hasNext").
I know that the approach below might not strictly make sense from a Java perspective because what I'm searching for is a for loop that does not loop through a Collection but logically it makes sense.
for (Node node : firstNode)
Otherwise I would need to do something like
Node node = getFirstNode();
while (node != null) {
//do stuff with current node
node = node.next;
}
The reason I don't want to use java.util.LinkedList is because of the lower amount of memory that will be used with the custom approach. Basically I also need the "next" and "previous" references in a Node so that I can easily access them with just having the Node at hand. If I would go with the java.util.LinkedList approach for each Node additionally I would need to keep an integer index to indicate at which index the object is located in the list and then be able to access "next" or "previous" or edit the list at that location in O(1) time.
Note that I would still prefer the java.util.LinkedList approach If there is a way to get away without needing the indexInList variable in the Node itself
Here is a very basic implementation of Iterator for a linked list that only iterates forward using the next pointer:
class NodeIterator implements Iterator<Node> {
Node current;
public NodeIterator(Node firstInList) {
this.current = firstInList;
}
#Override
public boolean hasNext() {
return current != null;
}
#Override
public Node next() {
Node savedCurrent = current;
current = current.next;
return savedCurrent;
}
}
To be able to use the enhanced for loop syntax, your custom linked list has to implement the Iterable interface. That interface has just one method, which creates a new iterator:
class LinkedList implements Iterable<Node> {
Node first;
#Override
public Iterator<Node> iterator() {
return new NodeIterator(first);
}
}
For reference, the Node class:
class Node {
Node next;
// add other fields you need
}

Pointers in LinkedList in 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.

Link List : initializing the header

So I'm working on a problem to print the nth element from the last of the list.
I have the method and a procedure figured out. This procedure finds the element.
public Node nth_element(Node head, int n){
// head to point to the first element in the list
// n is the element to be returned from the tail of the list
---do the function here---
}
Now when I'm in the main class and calling the above method. My Linked List class where the above method is declared initializes the head to null in its constructor.
How do i initialize the head?
This is my main class:
public class Main
{
static void main()
{
List l = new List() //initialize the list
//then i add the elements into the list using insert()
//display()
//now
**Node mynode = l.nth_element(head, value);**
// how do i initialize this head
}
In your self-defined linked list class List, you need to put head as the class field as
public class List {
private Node head = null;
// all method for List....
}
Then when you implement nthElement method, you don't have to use head as your first argument since it's already a class member and you can use it directly in your class methods. But if you do need to, then you can create a public method in List class:
public Node getHead() {
return head;
}
Your nthElement method will look like
public Node nthElement(Node head, int n) {
//implementation ...
}
Then in the main method, you can call nthElement like
Node mynode = l.nthElement(l.getHead(), value);
But make sure that your list is not empty. Otherwise, head is null.
Adding to #tonga's answer.
Your class List constructor should be something like:
private Node head;
public List(Node head)
{
this.head = head;
}
and then create your list
List l = new List(new Node(1));

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