adding list items or nodes in linked list - c++

I try the following c++ code to sort linked list Items while inserting value from the keyboard. Here I want to insert values at the beginning, somewhere in the middle and at the end in one Insertion function using while loop. my focus is only on how to insert and delete by finding the exact position using logical operations. Could you please help me in coding a linked list that can sort while inserting an item in c++
#include <iostream>
using namespace std;
struct listItem
{
//creating a node
int data;
struct listItem *next;
};
//function declaration
bool Initialize(listItem *head);
char menu();
void insertFirst(listItem *&head, listItem *&temp, int item);
void Insert(listItem *&head, listItem *&temp, int item);
void search(listItem *&head, listItem *&temp);
void deleteItem(listItem *&head, listItem *&temp);
void traverse(listItem *curr);
//function definition
bool Initialize(listItem *head)
{
//Initialize head and temp value to null
listItem *head = NULL;
listItem *temp = NULL;
}
char menu()
{
//menus
char choice;
cout<<"~~~~~~~~~~~~~~~~~~~~~~~~\n";
cout<<" Menu"<<endl;
cout<<" ........\n";
cout<<"1. Add an Item\n";
cout<<"2. Remove an Item\n";
cout<<"3. Search an Item\n";
cout<<"4. Traverse an Item\n";
cout<<"5. Exit\n";
cout<<"~~~~~~~~~~~~~~~~~~~~~~~~\n";
cin>>choice;
return choice;
}
//function to insert items
void Insert(listItem *&head, listItem *&temp, int item)
{
// check if the linked list is null
listItem *curr = new listItem;
if(head == NULL)
{
curr->data = item;
curr->next =NULL;
temp = curr;
head = curr;
}
//check if linked list is not empty and chose the right location
else if(head->data > item)
{
curr->data = item;
curr->next = temp->next;
temp = curr;
}
//check if linked list is not empty and chose the right location
else if(head->data < item && curr->next != NULL)
{
while (curr->data < item)
curr = curr->next;
temp->next = curr;
curr->data = item;
curr->next = temp;
temp = curr;
}
//check if linked list is not empty and chose the right location
else if(head->data < item)
{
while(head->data < item && curr->next == NULL)
curr = curr->next;
curr->data = item;
curr->next = NULL;
temp = curr;
}
else
cout<<item<<" is already there!!!\n";
}
void search(listItem *&head, listItem *&temp)
{
cout<<"NO code for searching item"<<endl;
}
void deleteItem(listItem *&head, listItem *&temp)
{
if(Initialize(head))
cout<<"The list is already Empty\n";
else if(head == temp)
{
delete head;
head = NULL;
temp = NULL;
}
else
{
listItem *curr = new listItem;
head = head->next;
delete curr;
}
}
void traverse(listItem *curr)
{
if(Initialize(curr))
cout<<"The list is already Empty\n";
else
{
cout<<"The list contains:\n";
while(curr != NULL)
{
cout<<curr->data<<endl;
curr = curr->next;
}
}
}
int main()
{
bool Initialize(head)
char choice;
int item;
do
{
choice = menu();
switch(choice)
{
case '1': cout<<"Please enter a number :";
cin>>item;
Insert(head, temp, item);
break;
case '2': //cout<<"Enter a number to delete :";
//cin>>item;
deleteItem(head, temp);
break;
case '3': search(head, temp);
break;
case '4': traverse(head);
break;
default: cout<<"System exit\n";
}
}
while(choice != '5');
return 0;
}

Inserting nodes. First... The code!
#include <iostream>
struct listItem
{
//creating a node
int data;
struct listItem *next;
};
//function to insert items
void Insert(listItem *&head, int item)
{
listItem **curr = &head; // start at head
while (*curr != NULL // while there is a node
&& (*curr)->data <= item ) // and the node goes before the new node
{
curr = &(*curr)->next; // get next node
}
*curr = new listItem{item, *curr}; // insert the new node
}
int main()
{
listItem * head = NULL; // empty linked list head
Insert(head, 1); // test insert to empty list
Insert(head, 0); // insert at head
Insert(head, 3); // insert at end
Insert(head, 2); // insert in the middle
}
I've removed all of the unnecessary code to focus on the insertion logic. You should always do this with a stack overflow question. To keep the noise in the question down, create a simple program that illustrates the problem and does nothing else. Read minimal reproducible example for more information and inspiration.
The code is almost self explanatory: Loop through the list until we find where to insert the node and then insert the node, but there are two little tricks.
There's the head node and there are next nodes. Both do the same job: Point to the next node in the list. Since they have different names, we need different code to deal with them. But what if we could make head and all of the next nodes have the same name? Then they can have the exact same code. That's curr's job. Now it doesn't matter if curr is head or a next. Most of the function's code just... goes away. And code that doesn't exist has no bugs.
The other problem with inserting into a singly linked list if you iterate to the node you need to insert ahead of, you've lost track of the node before it. To maintain the linkage you have to have the previous node's next pointer (or the head). You can maintain a pointer to the previous node, but this doesn't work with head since there is no head node, so you ruin the first trick and wind up with some nearly duplicated code. But if you abstract away the node and and store the address of head or the next pointer you have two pieces of information in one: The insertion point and the node after the insertion point. With
listItem **curr;
curr points to where we want to place the new node and *curr is the node after it. So
while (*curr != NULL // while there is a node
&& (*curr)->data <= item ) // and the node goes before the new node
{
curr = &(*curr)->next; // get next node
}
Works through the list until we find either the last node in the list, *curr is NULL, or the data at *curr goes after the node we want to insert, and then
*curr = new listItem{item, *curr};
creates a new node that is linked to the node that goes after and this new node is assigned to the pointer at the insertion point.
*curr, the pointer to the next item in the list, is set to point at a new listItem, just like any other use of new.
The twist is listItem is a very simple data structure and can take advantage of aggregate Initialization to initialize the listItem's members. The braces contain the values I want in the new listItem in the order they are declared in the structure. The first member variable, data, is set to item and the second, next, set to the current value of *curr, the next item in the list.
For a tiny instance of time you'll have *curr and the next of the new listItem pointing at the same listItem then the = operator updates the *curr to point at the newly created listItem instead.
Draw it out on a piece of paper and you'll see what's happening.

Related

LInked list not reversing

Bellow, I have some code that is supposed to display a linked list, reverse it, and then display the now reversed linked list, but it seems that it never displays. My only guess is that somehow the linked list is becoming null. What am I doing wrong? Both the reverse function and the function that should display the reversed array run, but there is no visual output after.
#include <iostream>
using namespace std;
class Node{
public:// creation of a simple Node class
int data;
Node* next;
};
class LinkedList{
public:
Node* head;
LinkedList() { head = NULL; }
void append( int x){
Node* temp = new Node;// allocate new node
Node* end = head;//used later
temp->data = x;//giving the node data
temp->next = NULL;//since this node will be last make the next of it NULL
if(head == NULL){// if list is empty then set new Node as the head
head = temp;
return;
}
while(end->next != NULL){// go until the last node
end = end->next;
}
end->next = temp;// change the next of the last node to the new node.
}
void reverse(){
Node* current = head;
Node* next = NULL;
Node* prev = NULL;
while(current != NULL){
next = current->next;// Store next
current->next = prev;// Reverse current node's pointer
prev = current;// Move pointers one position ahead.
current = next;
}
head = prev;
}
void display(){
while(head != NULL){// print data while not out of bounds
cout<<" "<<head->data;
head = head->next;
}
}
};
int main() {
LinkedList list;
list.append(1);
list.append(10);
list.append(32);
list.append(64);
list.append(102);
list.append(93);
list.display();
cout<<endl;
list.reverse();
cout<<"list reversed"<<endl;
list.display();
cout<<"reverse display ran"<<endl;
Turns out it was an oversight on my part, I should have set up a temporary variable that represented the head, in my current program I'm changing what head references in order to loop through the linked list, and thus setting head equal to null once it reaches the end of the list a correct way to write the display function would be:
void display(){
Node* temp = head;
while(temp != NULL){// print data while not out of bounds
cout<<" "<<temp->data;
temp = temp->next;
}
}
thanks to user Retired Ninja for reminding me that debuggers exist.

Deletion at end in linked lists

i am trying to write a simple program for deletion and insertion at the end of a linked list. I have managed to insert values at the end perfectly but I cannot understand what to do in deletion.
The delete function is deleteend(), display function is display() and insert function is insertend(int x) but I have problem only with delteend().
#include<iostream>
using namespace std;
struct node
{
int info;
node *next;
};
node *head = NULL;
void insertend(int x)
{
node *last = new node;
last->info = x;
last->next = NULL;
if (head == NULL)
head=last;
else
{
node *temp=head;
while(temp->next!=NULL)
temp=temp->next;
temp->next=last;
}
}
void display()
{
node *np=head;
while(np!=NULL)
{
cout<<np->info<<endl;
np=np->next;
}
}
void deleteend()
{
node *temp=head;
while(temp->next!=NULL)
temp=temp->next;
delete temp;
}
int main()
{
int data;
char ch;
do
{
cout<<"Enter value:";cin>>data;
cout<<endl;
insertend(data);
cout<<"Enter more values?(y/n):";cin>>ch;
cout<<endl;
} while(ch=='y');
cout<<"Your list is"<<endl;
display();
do
{
cout<<"Delete value from end?(y/n):";cin>>ch;
cout<<endl;
if(ch=='y')
deleteend();
} while(ch=='y');
cout<<"Your list is"<<endl;
display();
return 0;
}
You need to maintain a reference to the node before the node you want to delete, so that you can set the pointers correctly.
Since you are only supporting delete from end, your function should look more like this:
void deleteend()
{
// in case we have an empty list to begin with
if (!head) {
return;
}
if (head->next == NULL) {
// our list was one element, so delete head and set our list to null
delete head;
head = NULL;
return;
}
// here, have a node that points to the head
// and then have a node pointer to the next element
// Traverse the list until you hit the end
node *prev = head;
node *end = head->next;
while (end->next != NULL) {
prev = end;
end = end->next;
}
// once we're here, prev should be the second to last element
// and end is the last element
// so delete end and set prev->next to NULL
delete end;
prev->next = NULL;
}
This code can be adapted to delete any arbitrary node from the middle of the list.
For deleteend(), you need to set what is the next to last nodes next pointer to null. This can be done using two pointers, one for the current node and one for the previous node, or by using a pointer to pointer. If using two pointers, in the case of a list with a single node, then there is no previous node, only the head pointer. biryee's answer shows the two pointer method.
Example code for pointer to pointer:
void deleteend()
{
node **ppnode = &head; // ptr to head or a node's next pointer
if(head == NULL)
return;
// advance ppnode so *ppnode points to last node in list
while((*ppnode)->next != NULL)
ppnode = &(*ppnode)->next;
delete(*ppnode); // delete last node
*ppnode = NULL; // set what was pointer to last node to NULL
}

trying to make a simpler insertion at end of linked list program.Help needed with minor issues

I have managed to create a simple insertion at beginnning of linked list program but now i am struggling with insertion at end of linked list.
The program seems to be able to take values from user but the output list is not coming correct.Could you help me out?
If possible keep along the lines of my program as i am beginner and won't be able to understand a completely different method.
Logic i used-
If list is empty then insert value at beginning else if list is not empty then travel along the list till the next value being pointed at is NULL and then enter the new value in place of NULL.
#include<iostream>
using namespace std;
struct node
{
int data;
node *next;
};
node *start=NULL;
void insertend(int x)
{
node* temp=new node;
if(start==NULL)
temp->data=x;
else
{
while(temp!=NULL)
{
temp=temp->next;
}
temp->next=x;
}
}
void display()
{
node* disp=new node;
while(disp!=NULL)
{
cout<<disp->data<<endl;
disp=disp->next;
}
}
int main()
{
int x;
char ch;
do
{
cout<<"Enter data";cin>>x;
cout<<endl;
insertend(x);
cout<<"Do you want to continue?(y/n)";cin>>ch;
cout<<endl;
}while(ch=='y');
cout<<"Your list:"<<endl;
display();
}
The entry point to your list is the variable start. But you never set it. Take for example the first item a user inputs. You will call insertend(), it will check that start == NULL, but then it never sets start. You must set start = temp or something similar. You have the same problem in the else section -- you loop through the nodes starting with temp, but you should be starting with start. And again in the function display(), you create a pointer to a node and start looping from it, but it will have no data -- you should use start as the starting point of your loop.
struct node{
int data;
node* next;
};
node *first = NULL, *last = NULL;
void insert(int x){
if(first == NULL){
first = new node;
first->data = x;
first->next = NULL;
}else if(last == NULL){
last = new node;
last->data = x;
first->next = last;
last->next = NULL;
}else{
node *n = new node;
n->data = x;
n->next = NULL;
last->next = n;
last = n;
}
}
As you can see I am keeping track of first and last node in the list. Insert function checks if there is anything in the list with if(first == NULL)part. If there isn't it creates the first node. Similar thing happens with the else if. Finally in the else block we create a new node with data x. Then point the node stored in variable last to our new node and set last to be that node.
Here is the display function:
void display()
{
node *disp =first;
while(disp->next != NULL){
cout << disp->data << " ";
disp = disp->next;
}
cout << disp->data;
}
I also recommend that you do a cleanup after your program is finished running since you are creating new nodes.
void cleanup(node* n)
{
if(n->next == NULL)return delete n;
cleanup(n->next);
delete n;
}
and then at the end of main call cleanup(first)
Hope this makes sense :) Have a nice day!

Delete a value in a sorted Linked list

Hey I created a function that inserts inputed values into a sorted linked list, and now I'm trying to create another function to delete an entered value in a linked list. Currently I am getting an infinite loop of rick james and it is incredibly frustrating.
typedef int ListItemType; // global value in my header file
ListItemType item; // assigned in head file under ListNode struct
bool List::remove(const ListItemType& removedItem) {
ListNode *curr = head;
ListNode *prev = NULL;
//empty list
if(head == NULL){
cout<< "No items in the list";
}else{
//traverse the list
while(curr != NULL){
if(curr->item == removedItem){
break; //data has been found break loop
}else{
//increment loop
prev = curr;
curr = curr->next;
}
}//end while
//data has not been found
if(curr == NULL){
cout << "RICK JAMES";
}else{
//data has been found delete data
// case 1: delete at head node
if(head == curr){
head = head->next;
}else{
// case 2: delete after head
prev->next = curr->next;
}
delete curr;
size--;
return true;
}
}
return false;
}
the function logic looks ok to me...
If you're getting "RICK JAMES" all the time, it means it can not find the node to delete - may be something's wrong with the way you compare node's value with the function parameter...
function accepts
ListItemType& removedItem
which seems a little bit weird for int datatype, but I'm not sure how's the "item" field defined in ListNode... I would suggest to double check this. Good luck!

Linked List, insert at the end C++

I was writing a simple function to insert at the end of a linked list on C++, but finally it only shows the first data. I can't figure what's wrong. This is the function:
void InsertAtEnd (node* &firstNode, string name){
node* temp=firstNode;
while(temp!=NULL) temp=temp->next;
temp = new node;
temp->data=name;
temp->next=NULL;
if(firstNode==NULL) firstNode=temp;
}
What you wrote is:
if firstNode is null, it's replaced with the single node temp which
has no next node (and nobody's next is temp)
Else, if firstNode is not null, nothing happens, except that the temp
node is allocated and leaked.
Below is a more correct code:
void insertAtEnd(node* &first, string name) {
// create node
node* temp = new node;
temp->data = name;
temp->next = NULL;
if(!first) { // empty list becomes the new node
first = temp;
return;
} else { // find last and link the new node
node* last = first;
while(last->next) last=last->next;
last->next = temp;
}
}
Also, I would suggest adding a constructor to node:
struct node {
std::string data;
node* next;
node(const std::string & val, node* n = 0) : data(val), next(n) {}
node(node* n = 0) : next(n) {}
};
Which enables you to create the temp node like this:
node* temp = new node(name);
You've made two fundamental mistakes:
As you scroll through the list, you roll off the last element and start constructing in the void behind it. Finding the first NULL past the last element is useless. You must find the last element itself (one that has its 'next' equal NULL). Iterate over temp->next, not temp.
If you want to append the element at the end, you must overwrite the last pointer's NULL with its address. Instead, you write the new element at the beginning of the list.
void InsertAtEnd (node* &firstNode, string name)
{
node* newnode = new node;
newnode->data=name;
newnode->next=NULL;
if(firstNode == NULL)
{
firstNode=newnode;
}
else
{
node* last=firstNode;
while(last->next != NULL) last=last->next;
last->next = newnode;
}
}
Note, this gets a bit neater if you make sure never to feed NULL but have all lists always initialized with at least one element. Also, inserting at the beginning of list is much easier than appending at the end: newnode->next=firstNode; firstNode=newnode.
The last element in your list never has it's next pointer set to the new element in the list.
The problem is that you are replacing the head of the linked list with the new element, and in the process losing the reference to the actual list.
To insert at the end, you want to change the while condition to:
while(temp->next != null)
After the loop, temp will point to the last element in the list. Then create a new node:
node* newNode = new node;
newNode->data = name;
newNode->next = NULL;
Then change temps next to this new node:
temp->next = newNode;
You also do not need to pass firstNode as a reference, unless you want NULL to be treated as a linked list with length 0. In that case, you will need to significantly modify your method so it can handle the case where firstNode is NULL separately, as in that case you cannot evaluate firstNode->next without a segmentation fault.
If you don't want to use reference pointer, you could use pointer to pointer. My complete code goes like below:
void insertAtEnd(struct node **p,int new_data)
{
struct node *new_node=(struct node *)malloc(sizeof(struct node));
new_node->data=new_data;
new_node->next=NULL;
if((*p)==NULL)//if list is empty
{
*p=new_node;
return;
}
struct node* last=*p;//initailly points to the 1st node
while((last)->next != NULL)//traverse till the last node
last=last->next;
last->next=new_node;
}
void printlist(struct node *node)
{
while(node != NULL);
{
printf("%d->",node->data);
node=node->next;
}
}
int main()
{
struct node *root=NULL;
insertAtEnd(&root,1);
insertAtEnd(&root,2);
insertAtEnd(&root,3);
insertAtEnd(&root,4);
insertAtEnd(&root,5);
printlist(root);
return 0;
}
Understanding the need of the below two variables is key to understanding the problem:
struct node **p: Because we need to link it from the root node created in the main.
struct node* last: Because if not used, the original content will be changed with the contents of the next node inside the while loop. In the end only 2 elements will be printed, the last 2 nodes, which is not desired.
void addlast ( int a)
{
node* temp = new node;
temp->data = a;
temp->next = NULL;
temp->prev=NULL;
if(count == maxnum)
{
top = temp;
count++;
}
else
{
node* last = top;
while(last->next)
last=last->next;
last->next = temp;
}
}
#include <bits/stdc++.h>
using namespace std;
class Node
{
public:
int data;
Node *next;
};
void append(Node *first, int n)
{
Node *foo = new Node();
foo->data = n;
foo->next = NULL;
if (first == NULL)
{
first = foo;
}
else
{
Node *last = first;
while (last->next)
last = last->next;
last->next = foo;
}
}
void printList(Node *first)
{
while (first->next != NULL)
{
first = first->next;
cout << first->data << ' ';
}
}
int main()
{
Node *node = new Node();
append(node, 4);
append(node, 10);
append(node, 7);
printList(node);
return 0;
}
Output: 4 10 7
You can use this code:
void insertAtEnd(Node* firstNode, string name)
{
Node* newn = new Node; //create new node
while( firstNode->next != NULL ) //find the last element in yur list
firstNode = firstNode->next; //he is the one that points to NULL
firstNode->next = newn; //make it to point to the new element
newn->next = NULL; //make your new element to be the last (NULL)
newn->data = name; //assign data.
}
void InsertAtEnd (node* &firstNode, string name){
node* temp=firstNode;
while(temp && temp->next!=NULL) temp=temp->next;
node * temp1 = new node;
temp1->data=name;
temp1->next=NULL;
if(temp==NULL)
firstNode=temp1;
else
temp->next= temp1;
}
while loop will return at temp==null in your code instead you need to return last node pointer from while loop like this
while(temp && temp->next!=NULL) temp=temp->next;
and assign a new node to next pointer of the returned temp node will add the data to the tail of linked list.