Inserting a node in the end of a linked list - c++

Below fragment is invalid to inserting a node in the end of Linked List.
void insert_end(int item){
nodeptr newNode = new ListNode;
newNode->data = item;
newNode->next = NULL;
if(head == NULL){
head = newNode;
curr = head;
}else{
curr = head;
while(curr != NULL) curr = curr->next;
curr = newNode;
}
}
Another fragment that is valid to inserting a node in the end of Linked List.
void insert_end(int item){
nodeptr newNode = new ListNode;
newNode->data = item;
newNode->next = NULL;
if(head == NULL){
head = newNode;
curr = head;
}else{
curr = head;
while(curr->next != NULL) curr = curr->next;
curr->next = newNode;
}
}
My question is why 1st one is invalid? Actually two fragments should be similar.
Assume i have three nodes already. Now i want to inserting another node.
As first algorithm when curr = NULL, then while loop will not satisfied.
As second algorithm when curr->next = NULL then while loop will not satisfied.
so can i say first algorithm's 'curr' and second algorithm 'curr->next' both are similar, when "while loop" terminated?
if it's not similar then why?

You must understand a pointer is a variable which value is an address.
First algorithm is wrong because when you finish the iteration of while loop, curr points to NULL (address 0x0), and NULL is not a valid node of your list.
Second algoritm works because when you finish the iteration of while loop, curr points to last node of your list, and you add newNode to curr->next, replacing NULL by the address of newNode.
Hope this helps! :)

Related

How to delete "end" node from a circular linked list using only tail in c++?

I need to write three separate functions for node deletion in a circular singly linked list (deleteFront(), deleteMiddle() and deleteEnd()). I have to use only tail (last). For some reason, my deleteEnd() function deletes second to the last node. Can anyone please help?
struct node
{
int data;
struct node* next;
};
// some other functions
// 6 -> 5 -> 4 -> 3 -> deleteEnd() does 6 -> 5 -> 3 ->
void deleteEnd(struct node* last)
{
if (last != NULL)
{
if (last->next == last)
last = NULL;
else
{
node* temp = NULL;
node* temp1 = last;
while (temp1->next != last)
{
temp = temp1;
temp1 = temp1->next;
}
temp->next = temp1->next;
delete temp1;
}
}
}
There are several issues with your deleteEnd function:
There is no way that the caller can get the new tail reference, because the tail argument is passed by value. The tail parameter should be a pass-by-reference parameter.
The statement after the loop (in the else block) does not remove the correct node. After the loop, temp1->next will be equal to last, and it should be that node that is removed, yet your code removes temp1. You can fix this by changing the loop condition and initialise the temp and temp1 variables to point to one node further in the list.
The else block does not update tail, yet it is clear that it should, since the original tail node is deleted.
Less of an issue, but in C++ you should not use NULL, but nullptr.
Here is a correction:
void deleteEnd(struct node* &last) // corrected
{
if (last != nullptr)
{
if (last->next == last)
last = nullptr;
else
{
node* temp = last; // corrected
node* temp1 = last->next; // corrected
while (temp1 != last) // corrected
{
temp = temp1;
temp1 = temp1->next;
}
last = temp; // added
temp->next = temp1->next;
delete temp1;
}
}
}
Try This
Explanation : So we are receiving head of the Circular Linked List and taking a curr pointer and pointing it to the head of the CLL.
Then we are taking another pointer and keeping it one step before the curr pointer so that we can point that pointer's next(prev->next) to curr's next(curr->next) and free the curr node.
void deleteTail(Node* &head)
{
Node* curr = head;
Node* prev = NULL;
while(curr->next != head)
{
prev = curr;
curr = curr->next;
}
prev->next = curr->next;
curr->next = NULL;
delete curr;

Can someone explain this While loop in a linked list to me?

I'm confused with this while loop statement while creating a linked list: while(curr->next != NULL) But curr->next will always be NULL since we never initialized curr->next to point to anything, so that while loop should never run!
Can someone explain this, please?? The code snippet is as follows:
if (head != NULL)
{
curr = head;
while(curr->next != NULL)
{
curr = curr->next;
}
curr->next = n;
}
The complete code is shown below:
void AddNode(int addData)
{
nodePtr n = new node;
n->next = NULL;
n->data = addData;
if (head != NULL)
{
curr = head;
while(curr->next != NULL)
{
curr = curr->next;
}
curr->next = n;
}
else
{
head = n;
}
}
curr->next is null only on the second call to AddNode. The first call to AddNode we go to the head = n; branch. On the second call, curr->next will be null and the while loop doesn't execute at all. But notice what happens after that, at the end of that second call. The curr->next = n; makes curr->next no longer null, appending n to this linked list. By the third call, curr->next is not null. The while loop iterates through the nodes with curr = curr->next until curr->next is null again (last node), then appends to that last node via curr->next = n;.
It is checking it's current position and updating it every time until it reach end of a linked list
Example:
[1->[address of 2 ] ,2->[address of 3 ],3->[address of 4 ],4->[address of 5 ],5->[NULL ]]
current = 1;
while loop start check the next of current if its not null update current value
current =2
current =3
current=4
current=5
when it reach last element of linked list current next is now null it will stop.
outside of while loop add new element at the end of linked list

Delete nodes at positions divisible by 5 in linked list

I'm trying to delete every node at positions divisible by 5. With my approach I cannot seem to delete the last node:
void removeDivFive(Node* head){
int count = 0;
Node* temp = head;
while(temp != NULL){
count++;
if(count%5==0){
if(temp->next != NULL){
temp->value = temp->next->value;
temp->next = temp->next->next;
}
}
temp = temp->next;
}
while(head != NULL){
cout<<head->value;
head = head->next;
}
}
What I'm doing is copying the value of the next node to the current one and changing the pointer to the next next node. By doing this I cannot delete the last node if the list has 10 nodes.
Any help would be appreciated
First off, you are leaking the nodes you "remove". You need to actually destroy them since they are no longer being used.
Now, regarding your actual problem - what do you thing temp->next points at when the last node in the list is at a position divisible by 5? NOTHING! Thus, if (temp->next != NULL) evaluates as false, so you aren't even attempting to do anything with that last node, you just skip past it, which is why you are not removing it.
For every 5th node, you are copying the value of the next node into the current node, and then pointing the current node to skip the next node. In other words, you are not removing the 5th, 10th, 15th, etc nodes at all. You are actually removing the 6th, 11th, 16th, etc nodes instead. You need to remove the current node instead of the next node.
Which also means, you need to keep track of the previous node in the list so that you can re-link its next pointer to point at the next node that follows the current node being removed.
Try something more like this instead:
void removeDivFive(Node* head){
int count = 0;
Node *temp = head, *prev = NULL, *next;
while (temp != NULL){
++count;
next = temp->next;
if ((count % 5) == 0){
if (prev != NULL) {
prev->next = next;
}
delete temp;
}
else {
prev = temp;
}
temp = next;
}
}
Online Demo
Alternatively (as described by #GoswinvonBrederlow in comments):
void removeDivFive(Node* head){
int count = 0;
Node *temp = head, *next;
while (temp != NULL){
++count;
if ((count %4) == 0){
if (temp->next != NULL){
next = temp->next->next;
delete temp->next;
temp->next = next;
}
}
temp = temp->next;
}
}
Online Demo
As mentioned in the comments the deleted node isn't counted. So you need to delete a node every 4 counts instead of every 5. And if you use count%4 == 0 then the first time temp will point at node 4 and you want to delete the 5th node. So no need for temp->value = temp->next->value;, just remove the next node. Then next time around when count = 8 then temp will point at node 9. So again temp->next is the node to remove. ...
So the condition always fires for the node before the 5th, which is perfect for removing it.
void removeDivFive(Node* head){
int count = 0;
for (Node* temp = head; temp != NULL; temp = temp->next) {
count++;
if(count%4==0){
if(temp->next != NULL){
Node *t = temp->next;
temp->next = t->next;
delete t;
}
}
}
while(head != NULL){
cout<<head->value;
head = head->next;
}
}

Inserting at the end in doubly linked list

**following is my linked list code...
its not working for some reason. Can someone help me out here?
void insertAtTheEnd(node *&head, int data){
node *newNode= new node(data);
newNode->data=data;
node *temp=head;
while(temp!=NULL){
temp=temp->next;
}
temp->next=newNode;
newNode->next=NULL;
newNode->prev=temp->next;
}
As you have it coded, temp is guaranteed to be NULL when your while loop exits. Hence, temp->next=NULL will crash.
When you probe for a position in the list, you typically need to keep "previous" variable to point to the item before the one you are iterating with.
node* temp = head->next;
node* previous = head;
while (temp)
{
previous = temp;
temp = temp->next;
}
// when the while loop returns, `previous` is the last element in the list
previous->next = newNode;
newNode->prev = previous;
newNode->next = nullptr;
Another case you missing in your code. When head is NULL (empty list), you need to update head to be your newNode
// empty list - return the new node as head
if (head == nullptr)
{
newNode->next = nullptr;
newNode->prev = nullptr;
head = newNode;
return;
}

Why does destructor run into unallocated memory?

I have a singly-linked, circular linked list and am writing a destructor to delete all the nodes. The destructor first severs the head from the rest of the lest to prevent infinite circulation and then I loop through the list and delete all the nodes, eventually, the loop comes back to the head and deletes it as well. In the program I check to make sure that the pointer to the nodes is not NULL and I ran the debugger and it shows that it is NULL at a point which should end the loop, but instead the loop continues and runs into un-allocated memory. Here is my code:
node<T> *cur = head;
node<T> *nxt = head->next;
if (nxt) cur->next = nullptr;
cur = nxt;
// walk through the list and delete nodes
while (cur) {
cur = cur->next;
delete cur;
}
EDIT: Changed code to
node<T> *cur = head;
node<T> *nxt = head->next;
if (nxt) cur->next = nullptr;
cur = nxt;
// walk through the list and delete nodes
while (cur) {
nxt = cur->next;
delete cur;
cur = nxt;
}
EDIT 2: Changed code once more to handle edge cases, same problem still occurs.
if (head == NULL) return;
else if (head->next == head) delete head;
else {
node<T> *cur = head;
node<T> *nxt = head->next;
cur->next = nullptr;
cur = nxt;
while(cur) {
nxt = cur -> next;
delete cur;
cur = nxt;
}
}
It has nothing to do with the severing, your code to walk the list while deleting elements would be just as faulty in a non-circular list. You advance the pointer then delete what it points to (the next item).
You need to delete the current item (but, of course, you also need to have extracted its next field before that point because, once deleted, all content becomes undefined), something like:
while (cur != nullptr) {
node<T> *toDelete = cur;
cur = cur->next;
delete toDelete;
}
In terms of a full solution to what you need, the algorithm should be:
def delCircList(head):
# Ignore empty list.
if head == null:
return
# Special for one-element list.
if head.next == head:
free head
return
# Sever link and set start point.
curr = head.next
head.next = null
# Use normal deletion algorithm.
while curr != null:
toDelete = curr
curr = curr.next
free toDelete