I am trying to delete nodes with a given key and also want to display the updated Tail and Head node values. I am able to delete first node (Head) and cannot delete Tail node Please check my code below
public void delete(int key){
Node current = head;
while(current.next.data != key){
current = current.next;
}
if(current.next.data == key ){ //deleting current node
current.next = current.next.next;
if(current.next == head)
tail = current;
else if(current == head)
head = current.next;
}
}
My Main method:
public class Caller {
public static void main(String args[]){
Linklist theList = new Linklist();
theList.insertFirst(22);
theList.insertFirst(44);
theList.insertFirst(55);
theList.insertFirst(66);
theList.delete(22);
System.out.println("deleting 22");
theList.display();
theList.delete(66);
System.out.println("Deleting 66");
theList.insertLast(99);
theList.insertLast(11);
theList.display();
}
}
my insertLast method:
public void insertLast(int data){
Node newNode = new Node(data);
Node current = head;
while(current.next != head){
current = current.next;
}
current.next = newNode;
newNode.next = head;
tail = newNode;
}
and my output is :
deleting 22
Displaying list first ----> last
{ 66 }
{ 55 }
{ 44 }
Head : 66 Tail: 44
Deleting 66
Nothing happens after this code
This is one of the problems which are best solved by running through the algorithm step-by-step with pen and paper. I think the problem is not in removing the tail node, which your own log output shows as working, but in deleting the head node ('66' in this case). Yes, '66' was inserted last, but it was inserted upfront of anything else already in the list, thus making it the head node.
The problem is that you change the cyclic list's structure before you update the head/tail pointers. In the case of removing the head node, when the code gets to the current.next = current.next.next; line, current points to the tail node, current.next is the head node, and current.next.next is the head+1 node. By executing the assignment, current.next is made to point to the head+1 node, meaning that neither if(current.next == head) nor else if (current == head) will trigger. The head node is now outside of the cyclic list, but the head pointer still points to that node; and worse, head.next still points into the cyclic list.
Two more issues:
Major: the delete() method does not handle the removal of the last element of the list
Minor: the if(current.next.data == key ) is unnecessary because it is literally the stopping condition for the preceding while-loop.
I kept track of previous and current node and it worked!
public void delete(int key){
Node current = head;
Node prev = current;
while(current.data != key){
prev = current;
current = current.next;
}
if(current.data == key ){ //deleting current node
if(current == head){
prev = tail;
head = current.next;
}else if(current == tail){
tail = prev;
head = current.next;
}
prev.next = current.next;
}
}
Related
Here is the piece of code in java for inserting node at the end of the circular linked list, but its not working using this function but when I saw in the internet and used that then it worked. Can anyone suggest me that what is wrong with this piece of code?
//PUSH NODE AT END IN CIRCULAR LL
public void pushEnd(int new_data){
Node new_node = new Node(new_data);
if(head == null){
head = new_node;
new_node.next = head;
}
else{
Node temp = head;
while(temp.next!=null){
temp = temp.next;
}
temp.next = new_node;
new_node.next = head;
}
}
Does any node in a circular linked list have its next field as null ? If it is, then its not a circular linked list. In your code you are looping until you find a null for the next. In fact after the first inserted node , for the next insert the loop while ( temp.next != null ) never ends.
You need to get to the node whose next is head, that's your last node for the moment. You need to push your new node after that.
So your code should be:
public void pushEnd(int new_data){
Node new_node = new Node(new_data);
if(head == null){
head = new_node;
new_node.next = head;
}
else{
Node temp = head;
while(temp.next!=head){
temp = temp.next;
}
temp.next = new_node //assign the temp's next to new_node.
new_node.next = head; //then assign new_node's next to head
}
}
It's a circular list. temp.next will never be null, and so your while loop will never end. You need to change your logic a bit and check when temp.next == head.
I can't seem to figure out why inserting a node at the end of a doubly linked list is getting stuck in a loop. Either its stuck in a loop or null pointer. Also I'd like to know if public Node is better or public void when dealing with linked lists or any data structures.
public Node insertEnd(int data) {
Node newNode = new Node(data);
newNode.next = null;
if (head == null) {
head = newNode;
return newNode;
}
Node last = head;
while(last!=null) {
last = last.next;
last.next = newNode;
}
newNode.previous = last;
return newNode;
}
Well, its because of this part of the logic
Node last = head;
while(last!=null) {
last = last.next;
last.next = newNode; //// This shouldn't happen.
}
Once the linked list is already created, you're trying to go to the last element. However, during that traversal you've also changed the next pointer to which the node was pointing to.
Try to change your logic to:
public Node insertEnd(int data) {
Node newNode = new Node(data);
newNode.next = null;
if (head == null) {
head = newNode;
return newNode;
}
Node last = head;
while(last.next != null) {
last = last.next;
}
last.next = newNode;
newNode.previous = last;
return newNode;
}
In your while loop:
while(last!=null) {
last = last.next;
last.next = newNode;
}
The second line sets last.next to newNode so on the next iteration, last will be set to newNode, who's next field is null. You only want to set last.next to newNode once last.next == null (When you have reached the end of the list):
while(last.next != null) {
last = last.next;
}
last.next = newNode;
As for the second part of the question, it depends on the way a client/caller of this API would expect the output to be.
Are you writing this API to be used in another program you're writing? In that case, think about if it will be useful for you to get the newly created Node as a return value of this API, or if it is acceptable to leave it as void.
For reference, the Java implementation of the API has void as the return type. (https://docs.oracle.com/javase/7/docs/api/java/util/LinkedList.html#addLast(E))
To answer 1st part , you need to make following changes in your code -
Node last = head;
while(last.next!=null) { // be careful- it should be last.next!=null instead of last!=null , as it will give null pointer exception.
last = last.next;
}
last.next = newNode;
newNode.previous = last;
return newNode;
as the statement "last.next = newNode;" in while loop was setting last to newNode in the first iteration itself.
for 2nd part of your question, it depends on the requirement of calling function.
I've traced through my code to reverse a linked-list using recursion, and I cannot find anything wrong with it, but I know it does not work. Can anyone please explain why?
Node reverseLL (Node head) {
if(curr.next == null) {
head = curr;
return head;
}
Node curr = head.next;
prev = head;
head.next = prev;
head = next;
reverseLL(head.next);
}
Below is a working version of your code, added with some helping structures:
class LList {
Node head;
void reverse() {
head = rev(head, head.next);
}
private Node rev(Node node, Node next) {
if(next == null) return node; //return the node as head, if it hasn't got a next pointer.
if(node == this.head) node.next = null; //set the pointer of current head to null.
Node temp = next.next;
next.next = node; //reverse the pointer of node and next.
return rev(next, temp); //reverse pointer of next node and its next.
}
}
class Node {
int val;
Node next;
public Node(int val, Node next) {
this.val = val;
this.next = next;
}
}
You need to call reverseLL(head.next) before the switching, to traverse down the list and start from the last node upwards. This requires some more changes though.
There are two possible implementation.
First one with a pointer to the head (a class attribute) within your class
class Solution:
head: Optional[ListNode]
def reverseList(self, head: Optional[ListNode]) -> Optional[ListNode]:
node = head
if node == None:
return node
if node.next == None:
self.head = node
return
self.reverseList(node.next)
q = node.next
q.next = node
node.next = None
return self.head
Second solution, does not rely on a class attribute to conserve the head once you find it. It returns the pointer to the head through the recursive calls stack
def reverseList(head):
# Empty list is always None
if not head:
return None
# List of length 1 is already reversed
if not head.next:
return head
next = head.next
head.next = None
rest = reverseList(next)
next.next = head
return rest
So, considering the following conditions, is this correct:
conditions:
prev references the last node of the list
curr is null
public void insertQ(SinglyLinkedListNode Q){
if (prev.next.next == curr){
prev.next = Q;
Q.next = curr;
}
return;
}
Does the previous statement insert node Q into a linked list properly?
I am not able to understand your logic in adding a node to the end of a singly linked list. Your line if (prev.next.next == curr) is undefined as prev.next is itself null. I have added a snippet for adding a node in the end of a linked list.
void append(int data){
Node node = new Node(data);
if(head==null){
head = new Node(int data);
return;
}
new_node.next = null;
Node last = head;
while (last.next != null)
last = last.next;
last.next = new_node;
return;
}
I am having some trouble in deleting a node fro a circular linked list specifically deleting the head node.I tried to debug the code and problem that i found out was that the head node is not getting updated after deletion.that means if my list is 1->2->3->1(the 1 at the end here is actually the repetition of head node 1 to show circular link list ) and after trying to delete '1' the list becomes 1->2->3->2...So basically the the head node is not getting updated and hence when I try to print this linked list it enters infinite loop as the head node is encountered only once and the stopping condition is nover met again. below is the code which I have written for deletion
public class cirlinklist {
private int data;
private cirlinklist next;
private cirlinklist head;
public cirlinklist()
{
data = 0;
next = this;
}
public cirlinklist(int val)
{
data = val;
next = this;
}
public void cirlist(int val)
{
cirlinklist node = new cirlinklist(val);
if(this.next == this) //only one node present
{
node.next = this;
this.next = node;
}
else
{
cirlinklist temp = this.next;
//cirlinklist head = this;
/*while(node != head)
node = node.next;*/
node.next = temp.next; //adding after the last added node.For adding before last added node change to temp here and temp.next in next line
this.next.next = node;
}
}
public void printlist()
{
//cirlinklist head = this; //start node
cirlinklist node = this; //node for traversing and printing
System.out.println("Circular Link list data is:");
do
{
System.out.println(node.data);
node = node.next;
}
while(node != head);
System.out.println(node.data);
}
public void check()
{
}
public cirlinklist delete(int val)
{
head = this;
cirlinklist node = head;
cirlinklist node2 = node;
if(head.data == val) //if the node to be deleted is head node
{
//this = this.next;
while(node.next != head) //iterate till the last node i.e. the node which is pointing to head
{
node = node.next;
}
node.next = node.next.next; // update current node pointer to next node of head
//node = node.next;
head = head.next; //update head node
/*this.next = head.next.next;
this.data = head.next.data;*/
return this;
}
else // if node to be deleted is other than head node
{
while(node.data != val) // find the node
{
node = node.next;
node2.next = node;
}
node2.next = node.next; //updating next field of previous node to next of current node.current node deleted
node = null;
return this;
}
}
public static void main(String [] args)
{
cirlinklist obj = new cirlinklist(1);
cirlinklist obj2 = new cirlinklist();
//obj.cirlist(1);
obj.cirlist(2);
obj.cirlist(3);
obj.printlist();
obj2 = obj.delete(1);
System.out.println("Circular list after deletion is");
obj2.printlist();
}
}
Please tell me where I am going wrong
if(head.data == val) //if the node to be deleted is head node
{
//this = this.next;
while(node.next != head) //iterate till the last node i.e. the node which is pointing to head
{
node = node.next;
}
node.next = node.next.next; // update current node pointer to next node of head
//node = node.next;
head = head.next; //update head node
}
In this code, where is the head pointing to after
node.next = node.next.next ?
may be the problem lies there.
Since your code has changed quite a bit since this answer was posted, I am starting fresh. I can solve your problem as it exists currently, but you do have some issues with your list design that I will mention and suggest you redesign what you have.
First, your print function is breaking because you don't have anything that sets head, which you are using to determine when to keep printing.
Modify your constructors to:
public cirlinklist()
{
data = 0;
next = this;
head = this;
}
public cirlinklist(int val)
{
data = val;
next = this;
head = this;
}
Second, your delete function needs to return head since that's what you're modifying in that function.
I've posted the cleaner function here:
public cirlinklist delete(int val)
{
cirlinklist node = head;
if(head.data == val) //if the node to be deleted is head node
{
//this = this.next;
while(node.next != head) //iterate till the last node i.e. the node which is pointing to head
{
node = node.next;
}
node.next = node.next.next; // update current node pointer to next node of head
//node = node.next;
head = head.next; //update head node
/*this.next = head.next.next;
this.data = head.next.data;*/
return this;
}
else // if node to be deleted is other than head node
{
cirlinklist prev = node; // track previous node from current (node)
while(node.data != val) // find the node
{
prev = node;
node = node.next;
}
prev.next = node.next; //updating next field of previous node to next of current node.current node deleted
return head;
}
}
This should get you what you want.
However, there is a problem that you're not yet seeing, in that if you try to return head and then hope it's a copy of the list, it's not. You're actually modifying the head list and then distributing it to some other method when it returns, meaning that cirlist obj2 = obj.delete(1); is not going to give you a new copy of the deleted list, leaving obj untouched. You can see this if you add another delete operation after this one and print.
That being said, I modified the function to react properly when deleting a node in the middle.
One other thing you might also want to test for, is removing the tail node, as you might experience problems with that case too.
The last thing I would suggest is you redefine your data structures. You're using the identifier node in this case to represent a list node, when in fact, as you've got them defined, are actually lists themselves. A linked-list as is typically defined, is a bunch of nodes linked together, the entire collection being the list.
If you create a data structure to represent the node, that is, it's an object that has a data element, and a pointer to the next node, your list can be in a different class entirely and you can operate on the nodes while preserving only a single copy of the list, that you can control and copy with greater ease.
Something like this:
public class ListNode {
public int data;
public ListNode next = null;
public ListNode() {
data = 0;
}
public ListNode(int data) {
this.data = data;
}
public ListNode(ListNode node) {
if ( node != null) {
this.data = node.data;
this.next = node.next;
}
}
}
Then you can have another class that actually provides the operations
public class CircularLinkedList {
public ListNode head;
public CircularLinkedList(...) {}
public void addToList(int data) {}
public void deleteFromList(int data) {}
... // and so-on
}
The head in this case, is your list, and any time you make changes or need to manipulate it, you can define functions that will do so in terms of head and then act appropriately.
Good luck to you