Building Singly LinkedList - java

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

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
}

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

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.

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

Categories