Circular Linked List Node Insertion Java - java

I tried implementing the insert method for circular linked list. I think I had some success.
Problem:
When I display the list. The display method will loop because every next variable of the link is linked to a non-null node object. So head will never be a null object. From what I recall about singly linked list, head always point to the first node in the list or the first node with data inside of it.
My conceptual understanding of circular linked list:
From what I can understand circular linked is somewhat like a singly linked list but with a slight twist: the next variable of the tail object points to the head.
I'm coding it like the diagram has presented provided by the source link.
Source: http://sourcecodemania.com/circular-linked-lists/
public void insert(String data)
{
Link link = new Link(data);
if(head == null)
{
head = link;
tail= link;
}
else
{
tail.next = link;
tail = link;
tail.next = head;
}
}
public void display()
{
// good implementation for display #2
while(head != null)
{
// System.out.println (head.data);
head = head.next;
}
}

Once you insert at least one element, you would never come across null. It will keep on going till infinity.
Also, it might not be a good idea to modify head just for displaying the list. Operation like display should not have any side effects.
In stead, keep a member field size in your list class and update it in each insert and delete method.
Now you would know how many times you should iterate the loop.
ListClassName current = head; // Head is not modified.
for (int i = 0; i < this.size; i++) {
// System.out.println (current.data);
current = current.next;
}
Good luck.

You can keep a reference to the first Link object and check to make sure head is not equal to this object while looping:
public void display()
{
boolean first=true;
Link firstItem=null;
// good implementation for display #2
while(head != null && head!= firstItem)
{
if(first){
firstItem=head;
first=false;
}
// System.out.println (head.data);
head = head.next;
}
}

Related

Program took more time than expected error

Below is a program to reverse a doubly linked list in gfg.
When I try to submit, I get the following error
Your program took more time than expected. Time Limit Exceeded
Expected Time Limit 0.00sec.
Can anyone tell me how to decrease my program's time?
Code
public static Node reverseDLL(Node head)
{
Node p,cur;
p=head;
cur=head.next;
while(cur!=null)
{
if(cur.next==null)
{
p.next=cur.next;
cur.next=head;
head.prev=cur;
head=cur;
break;
}
p.next=cur.next;
cur.next.prev=p;
cur.next=head;
head.prev=cur;
head=cur;
cur=p.next;
}
return head;
}
Your code is not correct:
The prev member of the (original) tail node is not set correctly. It is not set in the if block, but in the previous iteration, where it got its value with cur.next.prev=p, which is setting it to the (original) head node. This creates an infinite loop in the data structure. In the end, none of the prev links is null. It might be that the testing framework keeps following those prev links in circles until a time out happens.
Also, the function assumes that head is not null. This may not be guaranteed.
There are also too many assignments happening. With a doubly linked list it is quite simple: just swap the value of next and prev in every node:
public static Node reverseDLL(Node head)
{
if (head == null) {
return null;
}
Node next = head.next;
while (next != null) {
head.next = head.prev;
head.prev = next;
head = next;
next = head.next;
}
head.next = head.prev;
head.prev = null;
return head;
}
this is classic solution for O(N) time, so I guess time constraint for this task is required to. solve it for O(1).
Take a look for this thread: https://www.google.com/url?sa=t&source=web&rct=j&url=https://discuss.codechef.com/t/reverse-a-doubly-linked-list-in-o-1/72850&ved=2ahUKEwjipdrQw_T1AhVYLTQIHahIDx8QFnoECBQQAQ&usg=AOvVaw1c0BDUotM0suEK7I4B9pQs

How to find the first value in a linked list?

I have a linked list I'm given and I need to find the first value in the list via a getFirst method.I need to display an error message and quit the program if the value is null. The linked list is already given to me link so:
class MyLinkedList
{
private class Node // inner class
{
private Node link;
private int x;
}
//----------------------------------
private Node first = null; // initial value is null
//----------------------------------
public void addFirst(int d)
{
Node newNode = new Node(); // create new node
newNode.x = d; // init data field in new node
newNode.link = first; // new node points to first node
first = newNode; // first now points to new node
}
//----------------------------------
public void traverse()
{
Node p = first;
while (p != null) // do loop until p goes null
{
System.out.println(p.x); // display data
p = p.link; // move p to next node
}
}
}
//==============================================
class TestMyLinkedList
{
public static void main(String[] args)
{
MyLinkedList list = new MyLinkedList();
list.addFirst(1);
list.addFirst(2);
list.addFirst(3);
System.out.println("Numbers on list");
list.traverse();
}
}
Here's what I tried out for the method:
public static Node getFirst(Node list)
{
if (list == null)
{
System.out.println("Error!");
System.exit(1);
}
return MyLinkedList.first;
}
I know this isn't exactly right, we just started this in my class so I'm having trouble understanding what's going on with it. Thank you!
I think you should look at https://docs.oracle.com/javase/7/docs/api/java/util/LinkedList.html and get an idea for the behavior of a linked list initially. Once you have an idea on how it behaves, you can think about how to add functionality around it. Right now you just have a single method which you call more than you should. What also might help is to create an interface and document it so you know what each method should do.
You should check that first isn't null in order to do what you describe in the question. Also, it is kind of weird that the first node autoreferences itself because usually it is left in null until you add another node
notice that the first value is linked to the first Node with is null. Then you have to check two things
Node == null (you got this)
Node.next == null (you have to do this)
When Node.next == null. It means that Node is first value because it is linked to the initial Node with is null.
Then you have
public static Node getFirst(Node list)
{
// if the list is empty
if (list == null)
{
System.out.println("Error!");
System.exit(1);
} else if(list.link == null) {
// this is the first value!
return list;
} else {
// keep searching recursive with the next Node
return getFirst(list.link);
}
}
The class MyLinkedList in your question follows the pattern of a stack data structure(At the time when i am writing this answer). That is: ever time you add a new element, the new element replaces the previously added element as the first element.
I guess you want to get 1 as your first element, if you have added elements 1,2,3 in that order. Correct me if i am wrong.
In that case your linked list and it's retrieval should be like this:
(Note: i have avoided private vars , public getter , settter , etc; to make code easily readable. But readers should add them.)
class Node{ int x; Node next; }
class LinkedList
{ Node head,tail;
void add(int y)
{ Node node = new Node();
node.x=y;
if(head==null)
head = tail = node;
else
tail = tail.next = node;
}
int getFirst()
{ if(head!=null)
return head.x;
else
throw new java.util.NoSuchElementException("List is empty");
}
}
If you look at java.util.LinkedList, you will find methods that are conventionally used in linked lists. If this is not a homework question, then i suggest you do not reinvent the wheel. Just use the existing libraries.
If you have to use the stack data structure, and you cannot change it, then i suggest you have to change your getFirst() like this:
int getFirst()
{ if(tail!=null)
return tail.x;
else
throw new java.util.NoSuchElementException("List is empty");
}
If you not allowed to add Node tail in your code, then your getFirst() will look like this:
int getFirst()
{ if(head==null)
throw new java.util.NoSuchElementException("List is empty");
Node node = head;
while(node.next!=null)
node=node.next;
return node.x;
}

Anyone know why this method for linked list keeps on going forever?

I have this linked list method that is used to insert before, so it takes a node and puts it before the beforeNode. Currently it does that, but then it goes on forever and makes the linked list infinitely big when it should only be four long. Does anyone see why it keeps on going?
private void insertBefore(Node aNode, Node beforeNode)
{
if(this.getPrevious(beforeNode) != null) {
this.getPrevious(beforeNode).setNext(aNode);
// aNode.setPrevious(beforeNode);
//this.getPrevious(this.getPrevious(beforeNode)).setNext(aNode);
} else {
head = aNode;
}
aNode.setNext(beforeNode);
// beforeNode.setPrevious(aNode);
}
Here is the print list method that could have something to do with it, but I dont think so
public void printList()
{
Node currentNode;
currentNode = this.getHead();
System.out.print("head ->");
while(currentNode!=null)
{
System.out.print(currentNode.getData().toString()+ " -> ");
currentNode = currentNode.getNext();
}
System.out.println("|||");
}
I think some how you are passing the same node for both aNode and beforeNode. In java, every object is a reference. Did you by any chance try to create aNode a copy of beforeNode ? It might have made both the same and causing the linked list to have a self loop. use a copy constructor or things like clone to get a duplicate node.

LinkedList remove conditions (last iterated item)

I am attempting to remove the last iterated element, with a custom iterator/linked list class. It for some reason only does this for the first item in the list (the head condition). Is there anything wrong with the conditions?
Should I, instead of the Else after If (prev=head), write If (next != null) to find middle nodes, and If (next = null) to find the last node?
Second question: to remove the items, should I also write prev.element = null (now I only have prev = null, and I suppose that erases the node but not its content.
Quite simply, what is wrong with my remove method, as I cannot figure it out myself. Thank you guys so much in advance. I have been working many hours with this but I still haven't got it working.
public E next() {
if (!hasNext())
throw new NoSuchElementException ();
prev = next;
E element = next.element;
next = next.next;
return element;
}
public void remove() {
if(prev == null) {
throw new IllegalStateException();
}
else {
if(prev == head){
head = head.next;
next = head;
}
else {
next = prev.next;
}
sizeOfList--;
prev = null;
}
}
You would need a while loop to be able to go through every node in the list until you hit the last one. As it is now, your code simply goes past the head, and then gets into the code that says sizeOfList-- and then prev = null;
You need something like this:
while (prev.next.next != null) {
prev = prev.next;
}
prev.next = null;
I do prev.next.next so that you can set the 2nd to last node in your linked list to point to a null value (which is done by prev.next = null;). Think of it this way: prev is the 2nd to last element in the list, prev.next is the last element, and obviously prev.next.next HAS to be null (because prev.next is LAST.) So once this is the case, delete the last element by setting the 2nd to last element to point to a null value.
And then decrement your list count.
This is my best guess with the given code
if(prev == head){ should change to if(prev.equals(head)){ Use equals method.
And I think you have to override equals method in the corresponding element class might definitely help.
== only checks for whether both variables refer to same object in memory, where as equals check Object state.
I hope it helps :).

Manual Linked List - Insert before method

This is part of an exercise we did in class, I just can't figure it out...
The required method is the insertBefore(object data) method wherein when a user choose this method it will prompt it to enter a data to be inserted before the reference data(input by user)
An example of how it should run:
// assuming linked list has data 1,2,3 inserted already
Choose Method:
1)Insert Before
choice: 1 // input by user
====Insert Before====
Enter Reference data: 2 // input by user
Enter Data to be inserted: 5 // input by user
supposed output: 1,5,2,3
Here's my code for this exercise: (This is inside a class called LinkList with variables
protected int end;
protected Node start;
and an inner class called Node)
private class Node
{
public char data;
public Node next;
public Node(char data)
{
this.data = data;
}
}
public void insertBef(char ref,char data)
{
Node temp = new Node(data);
Node current = start;
if(end!=0)
{
for(int i = 1; i<end; i++)
{
if(current == start)
{
Node newNode = start;
newNode.data = current.data;
newNode.next = temp;
current = current.next;
}
else if(current.data == ref)
{
Node newNode = current;
newNode.data = current.data;
newNode.next = temp;
current = current.next;
}
}
end++;
}
else
{
temp.next = start;
start = temp;
}
end++;
}
But when I run my code it ouputs 3,5, not 1,5,2,3! I can't see where I might have gone wrong...
Can someone please tell me where the mistake is, and explain how I might fix it?
I understand that to be able to insert before a reference value you should:
Make a new node for the new data
Make a temporary node for the reference value and link
Make the link of the data before the reference value point to the new node and make the link of the new node point to the temporary node
I just can't seem to figure out how to implement it in Java code...
When programming, if it seems hard, you're probably going about it the wrong way...
You only need one line of code to accomplish the task!
list.add(list.indexOf(reference), data);
Here's this line wrapped as an insertBefore method:
public static void insertBefore(List<Integer> list, int reference, int data) {
list.add(list.indexOf(reference), data);
}
Here's a test using your example:
public static void main(String[] args) {
List<Integer> list = new ArrayList<Integer>(Arrays.asList(1, 2, 3));
insertBefore(list, 2, 5);
System.out.println(list);
}
Output:
[1, 5, 2, 3]
Note: This code will throw an exception if the reference element is not found.
I'll leave it to you to plug that hole.
First things first: for loops are generally a bad idea with linked lists. while loops are much better; you can do something like while(next != null).
Looking at your code, you seem to have a few problems.
Your for loop is overly complicated, and doesn't seem to make a lot of sense. Here's how your loop should look:
Get head node
Begin looping through the list, checking the next node's value as you go
Once you find that the next node's value is the one you're looking for, creating a new node.
Insert the new node by setting its Next value to be equal to the current node's Next value, then set the current node's next value to be the new node.
Return from the function.
Your middle bullet point is actually unnecessary, and I have no idea what you use end for. Regardless, you seem to have the basic principle down, so I won't feel like I'm spoiling you by posting code.
Now, I'm not sure what your start is. Does it hold a value, or is it a dedicated head node? I'd vote for a dedicated head node, I generally find it easier to work with because you don't need to add code for a special case where the number should come before the head. So your start node should be "empty"; the value it holds is ignored, the only thing it's used for is to keep a pointer to the first legit node in the list. If you do this, the insertBef method becomes incredibly simple. NOTE: untested code to follow.
public void insertBef(char ref, char data)
{
Node current = start;
while( current.next != null )
{
if( current.next.value == ref )
{
Node n = new Node(data);
n.next = current.next;
current.next = n;
return;
}
current = current.next;
}
}
Please don't just copy the code. If you have questions, post them and I'll do my best to answer.

Categories

Resources