Linked List issue insert from middle C++ - 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
}

Related

I'm trying to implement a binary tree. My program stops abruptly after a few node insertions. What is going wrong?

I'm just trying out implementation of binary tree. It's not for a college class so I cannot ask a teacher :(
I have tried debugging it with the Codeblocks debugger but I'm still not understanding what is going wrong.
I am using class instead of struct. Currently I have only implemented insertion and inorder traversal functions.
For insertion function, I am checking if the root node is NULL or not. If it is NULL, the newNode becomes equal to the root node. Or else, I find the appropriate parent node and then append the newNode as its child.
And, in the inorder traversal function, is my recursion correct?
Edit: Turns out that I wasn't initializing my Node variables. My code is working after initializing those variables. Thanks for your help!
#include<iostream>
using namespace std;
class Node
{
public:
int data;
Node* left_child;
Node* right_child;
};
Node* root = NULL;
void insertion();
void inorder_travesal(Node*);
int main(){
char ch;
do{
int choice;
cout<<"\nEnter your choice: \n1. Insertion\n2. Inorder Traversal\n : ";
cin>>choice;
switch(choice){
case 1: insertion();
break;
case 2: inorder_travesal(root);
break;
}
cout<<"\nDo you want to continue?: ";
cin>>ch;
}while(ch == 'y');
return 0;
}
void insertion(){
int data;
cout<<"\nEnter data: ";
cin>>data;
Node* newNode = new Node;
newNode->data = data;
if(root == NULL)
{
root = newNode;
return;
}
else
{
Node* temp = root;
while(true){
if(temp->data > newNode->data)
{
if(temp->left_child == NULL)
{
temp->left_child = newNode;
return;
}
else
{
temp = temp->left_child;
}
}
else
{
if(temp->right_child == NULL)
{
temp->right_child = newNode;
return;
}
else
{
temp = temp->right_child;
}
}
}
}
inorder_travesal(root);
}
void inorder_travesal(Node* temp){
if(temp->left_child != NULL){
inorder_travesal(temp->left_child);
}
cout<<temp->data<<" ";
if(temp->right_child != NULL){
inorder_travesal(temp->right_child);
}
}

my code stops in the middle and has no error c++

case 1 work fine but case 2 and 3 just stop the loop and the program
and i cannot choose any other case after that as! i wonder why it stop the loop from going as choice here would never equal 0 which i believe it's the only reason would stop the loop from going forward! thanks in advance.
i also checked the functions and all of them seems fine to me i'm not sure if the problem could be with them
#include "stdafx.h"
#include <iostream>
using namespace std;
void insert_node(int new_data);
void print_node();
void delete_node();
int new_data;
char choice;
struct node {
int data;
node* next;
};
node* head = NULL;
void main()
{
do
{
cout << "Enter 1 to insert a new node \n";
cout << "Enter 2 to disply the list \n";
cout << "Enter 3 to delete the last node \n";
cin >> choice;
switch (choice)
{
case '1':
cout << "Enter the data \n";
cin >> new_data;
insert_node(new_data);
break;
case '2':
if (head != NULL)
print_node();
else
cout << "SORRY, your list is empty \n";
break;
case '3':
delete_node();
break;
default:
cout << "Invalid entry \n";
}
} while (choice != '0');
}
void insert_node(int new_data)
{
node* NewNode = new node;
NewNode->data = new_data;
if (head == NULL)
head = NewNode;
else
{
NewNode->next = head;
head = NewNode;
}
}
void print_node()
{
node* printer=head;
do
{
cout << printer->data<<" - ";
printer = printer->next;
} while (printer != NULL);
}
void delete_node()
{
if (head == NULL)
cout << "no node to be deleted \n";
else
{
node* curr = head;
node* prev = NULL;
while (curr->next != NULL)
{
prev = curr;
curr = curr->next;
}
if (prev == NULL)
{
delete(curr);
head = NULL;
return;
}
prev->next = NULL;
delete(curr);
}
}
This is bugged
void insert_node(int new_data)
{
node* NewNode = new node;
NewNode->data = new_data;
if (head == NULL)
head = NewNode;
else
{
NewNode->next = head;
head = NewNode;
}
}
it should be
void insert_node(int new_data)
{
node* NewNode = new node;
NewNode->data = new_data;
NewNode->next = head;
head = NewNode;
}
Your version fails to set next when adding the first node to the list. And as you can see there's no need to make head == NULL a special case.
Because you aren't creating the list correctly in the first place, any attempt to print or delete items from the list is likely to fail.
And your print_node function would fail on an empty list. It should be a while loop not a do ... while loop.
void print_node()
{
node* printer=head;
while (printer != NULL)
{
cout << printer->data<<" - ";
printer = printer->next;
}
}
Your delete_node function looks very suspicious to me as well.

C++ - adding a node to a circular linked list with sorting

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.

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;
}

delete a node at nth position IN 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.