delete a node at nth position IN C++ - c++

I am having problems deleting from an arbitrary position given in a linked list. I succeeded for the first position and last position of my list but got a runtime error when going for the nth position.
struct node
{
int number;
node *next;
};
struct Box
{
void insertAsFirstElement(node *&head, node *&last,int number);
void insert(node *&head, node *&last,int number);
void remove(node *&head, node *&last);
void showList(node *current);
};
bool isEmpty(node *head) {
return head == NULL;
}
char menu() {
char choice;
cout<<"Menu"<<"1. Add an item.\n"<<"2. Remove an item.\n"<<"3. Show the list.\n"<<"Exit\n";
cin >> choice;
return choice;
}
void insertAsFirstElement(node *&head, node *&last,int number) {
node *temp = new node;
temp->number = number;
temp->next = NULL;
head = temp;
last = temp;
}
void insert(node *&head, node *&last,int number) {
if(isEmpty(head))
insertAsFirstElement(head, last, number);
else {
node *temp = new node;
temp->number = number;
temp->next = NULL;
last->next = temp;
last = temp;
}
}
void remove(node *&head, node *&last,int number) {
cin>>number;
node *temp = new node;
if(isEmpty(head))
cout<< "this list is already empty.\n";
else if (head == last) {
delete head;
head = NULL;
last = NULL;
} else {
for(int i = 0; 1< number-2; i++)
/*node *temp = head;
head = head->next;
delete temp;*/
node *temp = head;
head = head->next;
temp= temp->next;
node* temp2 = temp->next;
temp->next = temp2->next;
delete temp2;
}
}
void showList(node *current) {
if(isEmpty(current))
cout << "The list is empty\n";
else {
cout << "The list contains:\n";
while(current != NULL) {
cout << current->number << endl;
current = current->next;
}
}
}
int main() {
node *head = NULL;
node *last = NULL;
char choice;
int number;
do{
choice = menu();
switch (choice) {
case'1':
cout << "please enter a number: ";
cin >> number;
insert (head,last,number);
break;
case'2':
remove(head,last,number);
break;
case '3':
showList(head);
break;
default:
cout<< "System exit\n";
}
}while (choice !='4');
}

Your loop condition in the removal function is wrong, it's not checking anything affected by the loop, so it would just run forever (or more likely, until it breaks something).
In addition, your remove is not matching its signature. Since you didn't really explain what you want it to do, it's hard to say how to fix it - is number the value you want to remove (what if there are multiple ones?) is it the index to remove? is it a number of elements to remove?
I'll assume it's the second, as it seems like what you were trying to do. In any cases you need to search for that item before deleting it, so instead of -
for(int i = 0; 1< number-2; i++)
try
for(int i = 0; i < number-1; i++)
The 1 was probably a typo, and it's enough to stop one element ahead (the index meaning is up to you, but if the head is 0, then deleting index 2 should run the loop once)
Then, you need to put some brackets around your loop, since right now you're only looping over the first line of code. Move the assignment of temp = head ahead of the loop, you only need to do it once, and loop over
temp= temp->next;
(if that's your only line you don't need brackets, but it's a good habit anyway).
That should bring you to the element ahead of your index. If that's the head, you need some special treatment, but otherwise don't change head, or you'll lose elements you want to keep.
The actual removal looks like it might work, but everytime you dereference next, you need to make sure it's not NULL.

Related

(C++) Getting inconsistent results while using Nodes/Linked Lists.

#include <iostream>
#include <memory>
using namespace std;
struct Node
{
int data;
Node* next;
};
void append(Node*&, int);
void printList(Node*);
void insertNode(Node*&, int, int);
void searchList(Node*, int, int);
int main()
{
Node* head = nullptr;
int initialCount = -1, userInput, newNodeLoc = -1, newNodeVal, searchVal;
/// INITIALIZE LIST
while(initialCount <= 0)
{
cout<<"Enter the number of initial nodes (must be at least 1): ";
cin>>initialCount;
}
cout<<endl;
for(int i = 0;i<initialCount;i++)
{
cout<<"Enter a number: ";
cin>>userInput;
append(head,userInput);
}
cout<<endl;
cout<<"Here are the initial values in the linked list: "<<endl;
printList(head);
cout<<"\nEnter a number for a new node to insert to the linked list: ";
cin>>newNodeVal;
cout<<endl;
cout<<"Enter which position you want to insert it (ex. "<<head->data<<" is at pos 1): ";
cin>>newNodeLoc;
while((newNodeLoc<=0 || newNodeLoc>initialCount))
{
cout<<"New position must be greater than 1 and less than " << initialCount+1 <<": ";
cin>>newNodeLoc;
}
newNodeLoc--;
insertNode(head, newNodeVal, newNodeLoc);
cout<<"\nHere is the updated linked list: "<<endl;
printList(head);
/// SEARCH
cout<<"\nEnter the number that you want to search for in the list: ";
cin>>searchVal;
cout<<endl;
initialCount++;
cout<<initialCount;
searchList(head,searchVal,initialCount);
return 0;
}
void printList(Node* head)
{
Node *n = head;
cout<<n->data<<endl;
while(n->next != nullptr) // print out all nodes values'
{
cout << n->next->data<<endl;
n = n->next;
}
}
void append(Node*& head, int val)
{
Node* temp = new Node;
temp->data = val;
temp->next = nullptr;
Node* ptr = head;
if(head == nullptr) // check if list is empty
{
head = temp;
}
else
{
while(ptr->next != nullptr) // if list isn't empty, get to last element set it equal to temp
{
ptr = ptr->next;
}
if(ptr->next == nullptr)
{
ptr->next = temp;
}
}
delete temp;
temp = nullptr;
}
void insertNode(Node*& head, int val, int loc)
{
Node* temp = new Node;
Node* prevLoc = new Node;
Node* curr = head;
temp->data = val;
int tempPos = 0;
while(curr->next != nullptr && tempPos != loc)
{
prevLoc = curr;
curr = curr->next;
tempPos++;
}
prevLoc->next = temp;
temp->next = curr;
delete temp;
delete prevLoc;
curr = nullptr;
prevLoc = nullptr;
}
void searchList(Node* head, int sVal, int iCount)
{
Node* curr = head;
int index=0;
while(curr->next != nullptr && curr->next->data != sVal)
{
curr = curr->next;
index++;
}
cout<<index;
cout<<iCount;
if(index != iCount)
{
cout<<"Number found at index "<<index<<" in the linked list!";
}
if(index-1 == iCount)
cout<<"Number could not be found in this linked list.";
delete curr;
curr = nullptr;
}
Hi there! I'm trying to implement append/prntlist/insertnode/search functions and I'm getting extremely inconsistent compiling results. Sometimes the code will run fine. Sometimes the code will randomly break. Other times it'll print out numbers on an infinite loop. I'm thinking it's a memory leak somewhere (in append/print functions), but I'm not super confident. It might also be a loop that's breaking the code. Any and all help is appreciated! I understand that the search function doesn't work so you can ignore it. Thank you!
In your append():
delete temp;
temp is your new element, that you've just append()ed to the list. Now that it's a part of the list, it gets immediately deleted. Good-bye!
The next to the last element of your linked list now points to deleted memory. Subsequent attempt to walk the list results in undefined behavior. Subsequent attempts to append more elements to the list will just make things even worse, scribbling over deleteed memory (if it wasn't scribbled over anyway, by the next new) and generally making a major mess of everything.
The memory allocation logic in insert() is similarly flawed. It's even worse. Two news and two deletes. Furthermore, the overall logic is also wrong. Its ostensible purpose is to insert one more element to the list, so it shouldn't be allocating two new nodes, only one will do. Both append() and insert() add one more node to the list; so only one node needs to be newed in both cases.
But the overall problem is erroneous deletions of newed elements, when they should not be newed, and they continue to be used. You cannot use anything after it gets deleted. It's gone. It ceased to exist. It joined the choir-invisible. It's an ex-object. But the shown code erroneously deletes an element after it gets added to the link list and, ostensibly, is still logically a part of the link list.

Adding value to end of linked list and removing from the front c++

I'm attempting to add items to the end of the list and remove them from the beginning of the list. The program compiles but crushes when I try to add items. I'm new to this concept an it's taking some time to settle in completely. Any help is appreciated..
Thanks!
#include<iostream>
using namespace std;
struct myNode
{
int val;
struct myNode *next;
};
class Cll
{
public:
myNode* head = new myNode;
myNode* tail = new myNode;
Cll()
{
head = NULL;
tail = NULL;
}
myNode* createAnode(int value)
{
myNode* temp;
temp = new myNode;
temp->val = value;
temp->next = NULL;
return temp;
}
void addingValues()
{
int numb;
cout<<"Enter the number to be added: ";
cin>>numb;
myNode *temp, *p;
temp = createAnode(numb);
p = head;
p = p-> next;
temp -> next = NULL ;
p -> next = temp;
}
void deletingValues()
{
myNode *s;
s = head;
head = s->next;
}
void showValues()
{
struct myNode *temp2;
temp2 = head;
while (temp2)
{
cout<<temp2->val<<"->";
temp2 = temp2->next;
}
cout<<"NULL"<<endl;
}
};
int main()
{
int pick ;
Cll cll;
int again;
do
{
cout<<"1.add"<<endl;
cout<<"2.delete"<<endl;
cout<<"3.show"<<endl;
cout<<"Enter choice : ";
cin>>pick;
switch(pick)
{
case 1:
cll.addingValues();
cout<<endl;
break;
case 2:
cll.deletingValues();
break;
case 3:
cll.showValues();
cout<<endl;
break;
}
cout << "Enter 1 to see again, enter 2 to quit"<< endl;
cin >> again;
} while (again == 1);
}
You are programming in c++, so I recommend to use std::list.
But if you like to do it yourself, and you like to ad a node at front of your single liked list, you first have to check if it is the first node or not.
If it is the first node your new node ist head and tail. If not the new node is the the head and its successor is the old head of the list. Adapt your code like this:
void addingValues()
{
int numb;
cout << "Enter the number to be added: ";
cin >> numb;
myNode *newNode = createAnode(numb);
if ( head == NULL ) // if list is empty the new node is the head and the tail
{
head = tail = newNode;
return;
}
tail->next = newNode; // successor of last node is new node and new node is tail
tail = newNode;
}
To delete a node from front of the list you have to check if the list is not empty and if it was the last node in the list:
void deletingValues()
{
if ( head == NULL )
return;
myNode *temp = head->next;
delete head;
head = temp;
if ( head == NULL )
tail == NULL;
}

Linked List issue insert from middle C++

I am new to linked lists, and now I face a problem on how to add the node into the middle of a list. Example like if I got a name list show below and when I add data one by one just like below sequence:
1.andrew
2.eric
3.madness
4.gerik
I want my data "gerik" in "madness" place when it show out. I am able to sort the data infront of "eric" but after "eric" i am not idea. I want my output just like below:
1.andrew
2.eric
3.gerik
4.madness
Below will be my example code, please help me by giving me advise or code sample:
#include <iostream>
#include <string>
#include <cstdlib>
#include <cstring>
using namespace std;
struct node
{
char f_name[20];
char l_name[20];
char u_id[10];
node *next;
};
node *head;
node *curr;
//prototype
void display();
void add();
void search_name();
void insert_data(node *tempnode);
void insert_before_head(node *tempnode);
void menu(char choice);
char pause;
//function start...
void search_name()
{
char name[20];
curr = head;
cin.ignore(30,'\n');
cout<<"Key In Last Name :"<<endl;
cin.get(name, 20);
cin.ignore(30,'\n');
while((curr->next != NULL) && (strcmp(curr->l_name, name) != 0))
{
curr = curr->next;
}
if(curr != NULL)
{
cout<<"Record Found !"<<endl;
cout<<"First Name"<<setw(16)<<"Last Name"<<setw(16)<<"User ID"<<endl;
cout<<"--------------------------------------------------------------"<<endl;
cout<<curr->f_name<<setw(20)<<curr->l_name<<setw(16)<<curr->u_id<<endl<<endl;
}
else
{
cout<<"No Match !"<<endl;
cout<<"Press 'Enter' To Continue"<<endl;
cin.get(pause = getch());
system("cls");
}
};
void display()
{
curr = head;
if(head != NULL)
{
cout<<"First Name"<<setw(16)<<"Last Name"<<setw(16)<<"User ID"<<endl;
cout<<"--------------------------------------------------------------"<<endl;
while(curr != NULL)
{
cout<<curr->f_name<<setw(20)<<curr->l_name<<setw(16)<<curr->u_id<<endl;
curr = curr->next;
}
}
else
{
cout<<"No Data. File storage Empty!"<<endl;
}
};
void add()
{
node *temp;
temp = new node;
cin.ignore(30, '\n');
cout<<"Key In First Name:"<<endl;
cin.get(temp->f_name, 20);
cin.ignore(30, '\n');
cout<<"Key In Last Name:"<<endl;
cin.get(temp->l_name, 20);
cin.ignore(30, '\n');
cout<<"Key In Your ID:"<<endl;
cin.get(temp->u_id, 10);
insert_data(temp);
};
void insert_data(node *tempnode)
{
node *temp;
if(head == NULL)
{
node *temp;
temp = new node;
temp = head;
tempnode->next = NULL;
head = tempnode;
}
else if(strcmp(tempnode->l_name, head->l_name) < 0)
{
insert_before_head(tempnode);
}
else
{
temp = new node;
curr = head;
while(curr->next != NULL)
{
curr = curr->next;
}
temp = tempnode;
curr->next = tempnode;
tempnode->next = NULL;
}
};
void insert_before_head(node *tempnode)
{
node *temp;
if(head != NULL)
{
temp = new node;
temp = tempnode;
tempnode->next = head;
head = tempnode;
}
};
void menu(int choice)
{
switch (choice)
{
case 1 :
add();
break;
case 2:
display();
break;
case 3:
search_name();
break;
case 4:
cout<<"Exit Program !"<<endl;
break;
default :
cout<<"Error! Program Terminate !"<<endl;
}
};
int main()
{
int choice;
node *temp;
head = NULL;
curr = NULL;
cout << "Data Stack Head And Any Position !" << endl;
system("cls");
do{
cout<<"1. Add Data."<<endl;
cout<<"2. Show Data. "<<endl;
cout<<"3. Search Last Name "<<endl;
cout<<"4. Exit. "<<endl;
cin >>choice;
menu(choice);
}while(choice != 4);
return 0;
}
To sort linked lists you need to use the divide and conquer strategy with merge sort.
In order to insert in the middle you need to create 2 nodes Node slow and Node fast. At first Node slow is head.next, Node fast is head.next.next and you keep moving those 2 by doing slow = slow.next and fast = fast.next.next, until you hit the end with Node fast. If you think about it, fast will be moving twice as fast as Node slow, so in the end Node slow will be in the middle. Then insert after that node.
We want to insert in our list newNode.
Let node X be the node, after which newNode should be inserted to preserve sorting order.
You can rewite your insert_data(...) function like in my example.
I took the code, sugested by WhozCraug and rewrote it to be more evident.
void insert_data(node *newNode)
{
node **pointerToTheNextPtr = &head;
// find position to insert new node
while (*pointerToTheNextPtr && strcmp((*pointerToTheNextPtr)->l_name, newNode->l_name) < 0)
pointerToTheNextPtr = &((*pointerToTheNextPtr)->next);
// here pointerToTheNextPtr stores the pointer to the X->next field
// insert new node between X and *(X->next)
newNode->next = *pointerToTheNextPtr; // set newNode->next = X->next
*pointerToTheNextPtr = newNode; // set X->next = newNode
}

Adding/ removing tail, showing list in reverse. linked list c++

I am working on a linked list, I made a menu (As a noob this greatly impressed me:)) and got the add front and remove front to work. although I want to be able to add in a node at the end then remove it and display it in reverse. I thought my removelast function looks like it would work but it doesn't. Not sure how to add to the tail, and no clue what so ever how to show in reverse. I looked up some guides but i am no good at understanding from text, I like to see examples pertaining to my problem.
Take a look!
#include <iostream>
using namespace std;
struct node //node structure
{
int number;
node *next;
};
bool isempty(node *head);
char menu();
void first(node *&head, node *&last, int number );
void insert(node *&head, node *&last, int number);
void removefirst(node *&head, node *&last);
void removelast(node *&head, node *&last);
void shownode(node *current);
void showreverse(node *&last);
bool isempty(node *head)
{
if(head == NULL)
return true;
else
return false;
}
char menu()
// I added a menu because in an actual application this is what you would have
//And it was fun :D
{
char choice;
cout<<"choose an option:"<<endl;
cout<<"1. Add Node."<<endl;
cout<<"2. Add Node to Last"<<endl
cout<<"3. Remove First Node."<<endl;
cout<<"4. Remove last node"<<endl;
cout<<"5. Show Node List."<<endl;
cout<<"6. Reverse Node List."<<endl;
cout<<endl;
cin>>choice;
cout<<endl;
return choice;
}
void first(node *&head, node *&last, int number ) //adding first
{
node *temp =new node;
temp->number = number;
temp->next = NULL;
head = temp;
last = temp;
}
void insert(node *&head, node *&last, int number)//adding more
{
if(isempty(head))
first(head, last, number);
else
{
node *temp =new node;
temp->number = number;
temp->next = NULL;
last->next = temp;
last = temp;
}
}
void addlast (node *&head, node *&last, int number)
{
node *temp =new node;
temp->number = number;
temp->last = NULL;
last->next = temp;
last = temp;
}
void removefirst(node *&head, node *&last)//destructor
{
if(isempty(head))
cout<<"List is empty."<<endl;
else if (head == last)
{
delete head;
head == NULL;
last == NULL;
}
else
{
node *temp = head;
head = head->next;
delete temp;
}
}
void removelast(node *&head, node *&last)
{
if(isempty(head))
cout<<"List is empty."<<endl;
else if (head == last)
{
delete last;
head == NULL;
last == NULL;
}
else
{
node *temp = last;
last = last->next;
delete temp;
}
}
void shownode(node *current)
{
if (isempty(current))
cout<<"list is empty"<<endl;
else
{
cout<<"Nodes in list:"<<endl;
while(current != NULL)
{
cout<<current->number<<endl;
current = current->next;
}
}
}
void showreverse(*&last)
{
}
int main()
{
node *head = NULL;
node *last = NULL;
char choice;
int number;
do{
choice = menu();
switch(choice)
{
case '1': cout<<"inert number:"<<endl;
cin>>number;
insert(head, last, number);
break;
case '2': addlast(head, last, number);
break;
case '3': removefirst(head, last);
break;
case '4': removelast(head, last);
break;
case '5': shownode(head);
break;
case '6': showreverse(last);
break;
default: cout<<"Exit";
}
}while(choice != '4');
return 0;
}
In your removelast(node *&head, node *&last) function when you delete the last element, the next member of the last but one node will still point to the last element you deleted.
node *temp = last;
last = last->next;
delete temp;
You are making a pointer to the same node, change its next member and than delete it, so the first two instructions are useless. The problem is at the last but one next member, but you have not way of changing it without iterating over the whole list. I think the best approach is to use a doubly linked list. With doubly linked list just interchange last pointer with head pointer, or parse it from last to head.

Inserting an integer at the end of the list and deleting at nth position

So, in my linked list program, what I want it to do is to ask the user how many numbers to input, and enter the numbers, and add those numbers at the end of the list. Then, it will print the list. After that, the user will choose a position of element in the list to delete and the list will be printed again.
#include <iostream>
using namespace std;
struct Node{
int data;
Node* link;
};
Node* head;
void Insert(int data){ //insert an integer at the end of the list
Node* temp = new Node();
Node* temp2 = new Node();
temp->data = data;
temp->link = NULL;
if(head = NULL){
head = temp;
return;
}
temp2 = head;
while(temp2->link != NULL){
temp2 = temp2->link;
}
temp2->link = temp;
}
void Delete(int n){ //delete an integer at nth position
Node* temp1 = new Node();
temp1 = head;
if(n == 1){ //if the first node is to be deleted
head = temp1->link; //now head points to second node
delete temp1; //delete first node
return;
}
for(int i = 0; i < n-2; i++){
temp1 = temp1->link; //temp1 points to (n-1)th node
}
Node* temp2 = temp1->link; //temp2 points to nth node
temp1->link = temp2->link; // pointing to (n+1)th node
delete temp2; //deleting nth node
}
void Print(){ //print out the list
Node* printNode = head;
cout << "List: ";
while(printNode != NULL){
cout << printNode->data;
cout << " ";
printNode = printNode->link;
}
cout << "\n";
}
int main(){
int x, count, n;
head = NULL; //start with an empty list
cout << "How many numbers? " << endl;
cin >> count;
for(int i = 0; i < count; i++){
cout << "Enter number: ";
cin >> x;
Insert(x);
}
Print();
cout << "Enter position to delete: ";
cin >> n;
Delete(n);
Print();
return 0;
}
After accepting the first number, the program stops working. Can I know where I did the code wrong and what can I do to make this code more efficient? Thanks in advance.
Big facepalm on my part, only a small mistake. Code has been corrected.
if(head == NULL){
head = temp;
return;
}
You might need to rethink your insertion function. The part that your code crashes on is during the while loop insertion. If you want temp2 to hold data then you need to dynamically allocate space for it which you did. However, you are just using it as a position indicator (to traverse the list) - so why do you need to allocate space just to point to head or any other nodes location in your list?
Here's how I would insert into the list (at the back of course):
void Insert(int data){ //insert an integer at the end of the list
Node* temp = new Node();
// This is to ensure that temp was created -> Also called defensive programming.
if (!temp)
{
cout << "We did not have enough space alloted to dynamically allocate a node!" << endl;
exit(1);
}
temp->data = data; // Bad nominclature for program; Don't use the same name twice.
temp->link = NULL;
if (head == NULL)
{
head = temp;
}
else
{
// This is to help traverse the linked list without having to
// manipulate the position of what head points to.
Node *Pos_Indicator = head;
while (Pos_Indicator->link != NULL)
{
Pos_Indicator = Pos_Indicator->link;
}
// We are at the end of the list, it is now safe to add.
Pos_Indicator->link = temp;
// Should probably have a check here for whether it was successful or not.
}
}
I was able to compile and run your code to completion with no other problems. Let me know if this helps!
EDIT: or you know (head = NULL) to (head == NULL) works too :(