how to insert into circular list (stuck in loop) - c++

I have this insert function that is suppose to insert into a linked list in ascending order. I think I have the function right. The problem is that I am stuck in a loop and I don't know why because everything compiles.
void list::insertElement(int element)
{
//ascending order
node *temp, *curr;
temp = new node;
temp->item = element;
numberofelements++;
if(head ==NULL)
{
head = temp;
head->next = head;
}
else {
curr = head;
do
{
if (((curr->item <= element)&& (curr->next->item >=element)) ||curr->next==head)
{
temp->next = curr->next;
curr->next = temp;
if (element < head -> item)
{
head = temp;
}
}
curr = curr->next;
}while(curr!= head);
}
}//end of function

tl;dr : add a retrun just after you have inserted
the problem is, when you insert, you don't stop the loop, as the loop stops only when current==head
when you insert, current isn't modified, so it's on the element before the one inserted, so then the curr = curr->next; put it on the inserted element, so next element is head and the element and the inserting condition is met again of course, so it's inserted again, and when it's inserted again, executing
temp->next = curr->next;
curr->next = temp;
make them looping, because temp->next = current->next = temp
PS : even if it is here obvious, when you use a struct or class you should really give us how it is defined exactly (functionnal code always make more people able to help you fast)

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

What's wrong with the insert at the end operation in this Linked List?

I have written this code for implementing Linked List in c++. It worked perfectly till i added the insert at end function to it. Please see what's wrong! Without the insertatend function, output is correct. After adding that function, the output is 1 10 which is actually the insert at start and end's outputs.
void List::insertatend(int num)
{
Node *new_node=new Node(num);
if(listptr==NULL)
listptr=new_node;
else
for(Node *temp=listptr; temp->next!=NULL; temp=temp->next)
temp->next=new_node;
}
The problem is in the lines:
for(Node *temp=listptr; temp->next!=NULL; temp=temp->next)
temp->next=new_node;
It seems like you haven't walked through the logic of how the code works.
You will first need to iterate until temp->next is NULL and then use
temp->next=new_node;
The code to implement that logic is:
Node* temp = listptr;
for ( ; temp->next != NULL; temp = temp->next )
{
// Do nothing in the loop.
}
temp->next = new_node;
Here's the updated function:
void List::insertatend(int num)
{
Node* new_node = new Node(num);
if( listptr == NULL)
{
listptr = new_node;
}
else
{
Node* temp = listptr;
for ( ; temp->next != NULL; temp = temp->next )
{
}
temp->next = new_node;
}
}
Go through the basic logic of how to add the every new node at end of previous node.Bug is in below two lines of insertatend function, explanation I mentioned in comments.
for(Node *temp=listptr; temp->next!=NULL; temp=temp->next) //it should be dummy loop
temp->next=new_node;//In all old nodes next part will replace by new_node which is wrong
Modiy Insert_end() function as
void List::insertatend(int num)
{
Node *new_node=new Node(num);
if(listptr==NULL)
listptr=new_node;
else{
Node *temp=listptr;
for( temp ; temp->next!=NULL ; temp=temp->next); /** rotate dummy loop until temp is not reaching to last node **/
temp->next = new_node;// in last node next put the new node address
new_node->next = 0; // and new node nnext put the zero
}
}

Linked list issue with multiple parameters

So I am trying to sort nodes according to their location (an integer) and then by the date (year and month). When I use my overloaded operator to print my linked list, it shows that the list is only inserting one of the wanted nodes meaning that my insert function is not correct. It is not giving any errors, it is just not running as expected. My insert function is below. Does anyone have any ideas as to what is wrong?
void LinkedList::insert(int location, int year, int month, double temperature) {
// Implement this function
Node* newNode = new Node();
newNode->loc = location;
newNode->yr = year;
newNode->mo = month;
newNode->temp = temperature;
Node* tempNode = head;
Node* previousNode = nullptr;
if(tail == nullptr & head == nullptr){
head = newNode;
}
while(tempNode != nullptr){
if((tempNode->loc == newNode->loc) && (tempNode->yr == newNode->yr)){
if(tempNode->mo > newNode->mo){
newNode->next = tempNode->next;
tempNode->next = newNode;
}
if(tempNode->mo < newNode->mo){
newNode->next = tempNode;
}
}
if(tempNode->loc > newNode->loc){
newNode->next = tempNode->next;
tempNode->next = newNode;
}
if(tempNode->loc < newNode->loc){
newNode->next = tempNode->next;
tempNode->next = newNode;
}
tempNode = tempNode->next;
}
}
The reason you are not getting the linkedlist properly is because you are making a mistake in pointer manipulation. When you assign cur->next=data->next;
you are basically breaking the list since data->next doesnot point to next node in the list.
Also, note that since this is a single linked list [meaning it has only one pointer forward] you can only insert nodes ahead of the current node.
Try something like this:
if (cur->loc > data->loc) {
data->next = cur->next; // This will insert data in middle of
cur->next = data; // cur and cur->next
}
There are multiple checks you will need to do if you want to insert in a increasing or decreasing order.
Make different cases for when you insert the first element of the list, insert at head, insert at tail and insert in the middle of linkedlist.
Also, at tail node make sure that its next is always set to null.

Sorting a Singly Linked List With Pointers

I am trying to sort a singly linked list using bubble sort by manipulating ONLY the pointers, no keys.
The following gets stuck in the for loop and loops infinitely. I don't understand why this is. Can anybody explain to me why the end of the list is not being found?
Node* sort_list(Node* head)
{
Node * temp;
Node * curr;
for(bool didSwap = true; didSwap; ) {
didSwap = false;
for(curr = head; curr->next != NULL; curr = curr->next) {
if(curr->key > curr->next->key) {
temp = curr;
curr = curr->next;
curr->next = temp;
didSwap = true;
}
cout << curr->next->key << endl;
}
}
return head;
}
If I change the code so that the keys (data) are swapped, then the function works properly but for some reason I am not able make it work by manipulating only pointers.
Logical Error, you are creating an infinite loop with following code -
temp = curr;
curr = curr->next;
curr->next = temp;
I,e next_of_current is pointing to current, so curr->next will always be curr and never will be NULL;
Next you should use previous pointer to fix your list because your list can be traversed in a single direction. So, Think -
If A->B->C->NULL; and you make C and B swap then the new list will still point to A->B and next iteration will be wrong ... because you are not modifying your previous next.
So, another implementation may be -
Node* sort_list(Node* head) {
Node * curr;
Node * prev;
for(bool didSwap = true; didSwap; ) {
didSwap = false;
prev = head;
for(curr = head; curr->next != NULL; curr = curr->next) {
if(curr->key > curr->next->key) {
if (head == curr) {
head = curr->next;
curr->next = head->next;
head->next = curr;
prev = head;
} else {
prev->next = curr->next;
curr->next = prev->next->next;
prev->next->next = curr
}
didSwap = true;
} else if (head != curr) {
prev = prev->next;
}
//cout << curr->next->key << endl; // <- this may cause crash if curr->next now points to NULL; (i,e last element)
}
}
return head;
}
Hope this helps, regards.
You have following problem:
Let you have list with three members: ptr1->ptr2->ptr3. Before swap you have following pointer set: curr=ptr1; curr->next=ptr2; curr->next->next=ptr3. When you perform swap you receive curr=ptr2; curr->next=ptr1; curr->next->next=ptr2.
E.g. you lost ptr3. You need to change code of inner loop with following:
temp = curr;
temp->next = curr->next->next; // Save ptr3
curr = curr->next;
curr->next = temp;
didSwap = true;
The field you want to swap is the value. However, if you swap the node, the next field will change, the question becomes a little more complex, you need keep the next field right. In a word, change value is a simple and good method.
node *sorted_list(node *head) {
node *index1,*index2;
for(index1=head;index1->next!=NULL;index1=index1->next) {
for(index2=index1->next;index2!=NULL;index2=index2->next) {
if(index1->data>index2->data) {
int temp=index1->data;
index1->data=index2->data;
index2->data=temp;
}
}
}
return head;
}