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.
Related
I have to create a circular linked list with a function, which adds a node on a particular position (the list should be sorted in ascending order by the value of a variable info). The function is called add_node. I thought that the best would be to create two pointers - to head and to the next node and then use while loop to compare next elements with a new node, and if it gets on a proper place - put it between those two. Unfortunately, the function works only when I add elements with smaller values than the biggest in list. How should this function look like to arrange the nodes correctly?
Code:
#include<iostream>
#include<cstdio>
#include<cstdlib>
using namespace std;
class Circular
{
struct node
{
int info;
struct node *next;
}*head;
public:
void create_node(int value);
void add_node(int value);
void display_list();
Circular()
{
head = nullptr;
}
};
void Circular::create_node(int value)
{
node *newnode;
newnode = new node;
newnode->info = value;
if (head == nullptr)
{
head = newnode;
newnode->next = head;
}
else
{
newnode->next = head->next;
head->next = newnode;
head = newnode;
}
}
void Circular::add_node(int value)
{
if (head == nullptr)
{
cout<<"List has not been created yet"<<endl;
return;
}
node *newnode, *ptr2, *ptr1;
newnode = new node;
newnode->info = value;
newnode->next=nullptr;
ptr1=head;
ptr2=head->next;
while(newnode->info > ptr2->info)
{
ptr1 = ptr1->next;
ptr2 = ptr2->next;
if(ptr2 == head) break;
}
ptr1->next = newnode;
newnode->next = ptr2;
}
void Circular::display_list()
{
node *s;
if (head == nullptr)
{
cout<<"List is empty"<<endl;
return;
}
s = head->next;
cout<<"Circular Link List: "<<endl;
while (s != head)
{
cout<<s->info<<"->";
s = s->next;
}
cout<<s->info<<endl<<endl;
}
int main()
{
int choice, element;
Circular cl;
while (1)
{
cout<<"1.Create node"<<endl;
cout<<"2.Add node"<<endl;
cout<<"3.Display"<<endl;
cout<<"9.Quit"<<endl;
cout<<"Enter your choice : ";
cin>>choice;
switch(choice)
{
case 1:
cout<<"Enter the element: ";
cin>>element;
cl.create_node(element);
cout<<endl;
break;
case 2:
cout<<"Enter the element: ";
cin>>element;
cl.add_node(element);
cout<<endl;
break;
case 3:
cl.display_list();
break;
case 9:
exit(1);
break;
default:
cout<<"Wrong choice"<<endl;
}
}
return 0;
}
I've come up with this:
void Circular::add_node(int value)
{
node *newnode, *ptr2, *ptr1, *temp;
newnode = new node;
newnode->info = value;
newnode->next=nullptr;
if (head == nullptr)
{
head = newnode;
newnode->next = head;
}
ptr1=head;
ptr2=head->next;
while(newnode->info > ptr2->info)
{
ptr1 = ptr1->next;
ptr2 = ptr2->next;
if(ptr2 == head) break;
}
if( ptr2->info < newnode->info )
{
temp=new node;
temp->info= ptr2->info;
temp->next= ptr2->next;
ptr2->next=newnode;
newnode->next=temp->next;
head=newnode;
delete temp;
}
else
{
ptr1->next = newnode;
newnode->next = ptr2;
}
}
It seems that it works. However, I wonder is there a better way to do it?
If a node is inserted before head, then then the last node's next pointer is not updated to point to the new head node, and the code currently doesn't have an easy way to find the last node in the list.
The usual way to handle this is also have tail pointer (pointer to the last node). Since this is a circular list, you only need to maintain a tail pointer for the class, since head can be created at anytime using head = tail->next;
Optional: add_node can be updated to handle an empty list, eliminating the need for create_node.
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.
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
}
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question appears to be off-topic because it lacks sufficient information to diagnose the problem. Describe your problem in more detail or include a minimal example in the question itself.
Closed 8 years ago.
Improve this question
I created a program for my homework that deals with linked lists. It ran fine before i entered a number and then it crashed on me giving me a segmentation fault error.
I know what that means but i cannot find the the issue.
Take a look and see if you could help me out! Thanks!
#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 remove(node *&head, node *&last);
void shownode(node *current);
bool isempty(node *head)
{
if(head = NULL)
return true;
else
return false;
}
char menu()
{
char choice;
cout<<"choose and option:"<<endl;
cout<<"1. Add Node."<<endl;
cout<<"2. Remove Node."<<endl;
cout<<"3. Show Node List."<<endl;
cout<<"4. Exit Program."<<endl;
cin>>choice;
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 remove(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 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;
}
}
}
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': remove(head, last);
break;
case '3': shownode(head);
break;
default: cout<<"Exit";
}
}while(choice != '4');
return 0;
}
This is the error i got:
choose and option:
1. Add Node.
2. Remove Node.
3. Show Node List.
4. Exit Program.
1
inert number:
44
RUN FINISHED; Segmentation fault: 11; real time: 2s; user: 0ms; system: 0ms
First, this line of code,
if(head = NULL)
should be,
if(head == NULL)
No idea if you are misunderstanding '=' and '==', '=' for assign value and '==' judge if equal.
In bool isempty(node *head) function
if(head = NULL) => if (head == NULL)
In remove(node *&head, node *&last) function
else if (head == last)
{
delete head;
head == NULL;
last == NULL;
}
should be
else if (head == last)
{
delete head;
head = NULL;
last = NULL;
}
The delete from last functionality does not work properly. It shows that the node has been deleted but when I display it, it gets into an infinite loop and displays junk. Couldn't figure what's wrong!
Here's the code:
using namespace std;
class List
{
struct NODE
{
int item;
NODE *next;
};
NODE *Head,*Tail;
public:
List()
{
Head=NULL;
Tail=NULL;
}
~List()
{
while(Head->next!=NULL)
{
Delete_At_Head();
}
Delete_At_Head();
}
void Add_At_First(int);
void Add_At_Last(int);
void Delete_At_Head();
void Delete_At_Tail();
int Is_Empty();
void display();
};
void List::Add_At_First(int data)
{
NODE *temp;
temp=new NODE;
if(Head==NULL)
{
temp->item=data;
temp->next=NULL;
Head=temp;
Tail=Head;
}
else
{
temp->item=data;
temp->next=Head;
Head=temp;
}
cout<<"Node added at first!\n";
}
void List::Add_At_Last(int data)
{
NODE *temp;
temp=new NODE;
temp->item=data;
temp->next=NULL;
if(Head==NULL)
{
Head=temp;
Tail=temp;
}
else
{
Tail->next=temp;
Tail=temp;
}
cout<<"Node added at last!\n";
}
void List::Delete_At_Head()
{
NODE *temp;
temp=new NODE;
temp->item=Head->item;
temp->next=Head->next;
delete Head;
Head=temp->next;
delete temp;
cout<<"Node deleted from head!\n";
}
void List::Delete_At_Tail()//Problematic part
{
NODE *temp,*prev;
temp=new NODE;
prev=new NODE;
temp=Head;
while(temp->next!=NULL)
{
prev=temp;
temp=temp->next;
}
prev->next=NULL;
delete temp;
delete Tail;
Tail=prev;
delete prev;
cout<<"Node deleted from tail!\n";
}
int List::Is_Empty()
{
if(Head==NULL)
return 1;
else
return 0;
}
void List::display()//does not display after delete from tail
{
NODE *temp;
temp=new NODE;
temp->item=Head->item;
temp->next=Head->next;
do
{
cout<<temp->item<<"-->";
temp=temp->next;
}while(temp->next!=NULL);
cout<<temp->item;
}
int main()
{
List obj;
int ch,data;
do
{
cout<<"\n1.Display\n2.Add at first\n3.Add at last\n4.Delete at
head\n5.Delete at tail\n6.Exit\nEnter your choice: ";
cin>>ch;
switch(ch)
{
case 1:
{
if(obj.Is_Empty())
cout<<"List is Empty!\n";
else
obj.display();
break;
}
case 2:
{
cout<<"Enter data: ";
cin>>data;
obj.Add_At_First(data);
break;
}
case 3:
{
cout<<"Enter data: ";
cin>>data;
obj.Add_At_Last(data);
break;
}
case 4:
{
if(obj.Is_Empty())
cout<<"List is Empty!\n";
else
obj.Delete_At_Head();
break;
}
case 5:
{
if(obj.Is_Empty())
cout<<"List is Empty!\n";
else
obj.Delete_At_Tail();
break;
}
case 6:
{
break;
}
}
}while(ch!=6);
return 0;
}
The following should correctly delete the last item in the list:
void List::Delete_At_Tail()
{
if(Head == NULL) return;
// If only one item in the list, delete it and empty the list...
if(Head->next == NULL) {
delete Head;
Head = NULL;
Tail = NULL;
return;
}
// Find the last item in the list
NODE *temp = Head;
while(temp->next!=Tail)
{
temp=temp->next;
}
delete Tail;
temp->next=NULL;
Tail=temp;
cout<<"Node deleted from tail!\n";
}
You are definitely deleting too many objects in your Delete_At_Tail() (I assume this is the function you meant when you wrote delete_from_tail() or "delete from last"; when programming precision is everything!) function: you want to get rid of one object but you are deleteing three objects, including the predecessor of the deleted object. You should only delete the object you are removing and no other. Other than that the function looks OK.
BTW, since you are maintaining a pointer to the Tail you can improve the way to find the predecessor: you can find the node whose next is Tail. This avoids the awkward need to keep two variables up to date in the loop looking for the predecessor.