Deleting Node in Linked List C++ - c++

So I've been searching forums, but im still very new to the language and linked lists so I can barely decipher the results.
basically I made a delete function for my linked list.
I can currently Create a list, traverse the list, sort the list, search the list, and insert before any node in the linked list. I recycled some code from the insert to locate the point in the list where I could delete. My main point of confusion is how to link the previous points to the node that is after the one I am deleting.

I won't write a whole new linked list implementation but i can point out some of the problems with the code for you.
The trick is to stay one node ahead of the one you want to delete.
I have renamed entry to current for clarity
nodetype *current , *first, *next;
int akey;
// With this line your search will start from the second element.
// current =start->ptr;
// Should be
current = start;
// this is not needed. I am assuming the last node has NULL value for '->ptr'
// last=start;
next = current->ptr;
cout<<"Input Data You Would Like To Delete"<<endl;
cin>>akey;
// Check if the first node contains the data
// Assuming the list will have at least one element. i.e. current is not NULL
while (current->adata == akey)
{
// Delete it.
delete current;
// Update current for the while loop
current = next;
// update next too.
next = current->ptr;
}
// Now we know the first element doesn't contain the data.
// Update the pointer to the begging of the new list if anything is removed from the top.
first = current;
// This has unnecessary checks.
// ****Specifically (akey!=current->adata) will
// prevent you from entering the loop if it is false.
// while((akey!=current->adata)&&(current->ptr !=NULL))
while(next != NULL) // This should be enough
{
if(next->adata == akey)
{
// make the current node (before the 'deletion point')
// lined to the one after the 'deletion point (next of the next)
current->ptr = next->ptr;
// delete the node.
delete next;
// Make the next pointer point to the new next.
next = current->ptr
}
// Otherwise advance both current and next.
else {
current = next;
next = next->ptr;
}
}
// Use this to test it.
current = first;
while(current){
cout<<current->adata<<", ";
current = current->ptr;
}
This is not the cleanest way. However it is similar to your implementation so you can see where you went wrong.

#include <iostream>
#include <string>
// blank line(s) after includes
using namespace std; // some people will say to avoid this
// but I use it in examples for brevity
// blank line(s) around class def
class nodetype
{ // bracket on its own line
public: // non indented visibility specifier
nodetype(int value, nodetype *p) // constructor first declared in class
{
adata = value; // level of indentation for fn body
ptr = p; // spaces around operators like =
}
// blank line(s) between fns and vars
int adata;
nodetype *ptr;
};
// blank line(s) between class and fn
void LinkedListDelete(nodetype **start, int akey)
{
nodetype *current, **previous; // pointer *s are connected to vars
// blank line between section
previous = start;
current = *start;
// blank line between section
// I use blank lines a lot, they help
// me to organize my thoughts
while((current != NULL) && (akey != current->adata))
{ // indentation inside nested scope
previous = &current->ptr; // no space for unary operators like &
current = current->ptr; // assignments justified to same level
}
if (current != NULL)
{
*previous = current->ptr; // no space for unary *, space for =
delete current;
}
// more blank lines between sections
return;
}
void LinkedListPrint(nodetype *list) // no space for unary *
{ // brackets on their own lines
while (list != NULL) // space around !=
{
cout << "(Node: " << list->adata << ") ";
list = list->ptr; // spaces around <<
}
cout << endl;
}
int main()
{
nodetype *node = new nodetype(5, new nodetype(10, // justified stuff
new nodetype(7, new nodetype(14,
new nodetype(23, NULL)))));
// blank lines
cout << "Build linked list: ";
LinkedListPrint(node);
cout << "Removed node 7: ";
LinkedListDelete(&node, 7);
LinkedListPrint(node);
return 0;
}
I made this code based on the code you provided. It's not quite the same, I changed some things, but it does what you want it to. I had to guess what the structure of nodetype was, and I added a constructor for my convenience. I added some comments pointing out aspects of my style.
Notice that it's easier to read than the code you originally provided. Style is important. People will tell you that you have to use X or Y style, but what really matters is that you pick whatever style you like and stick to it consistently; it will make it easier for you to read and understand your own code quickly.
Believe me you, when you've written a lot of code, you stop being able to remember all of it at once, and being able to figure out what you were doing quickly is essential.

Consider the structure given below,
struct info
{
int data;
struct info *next;
};
if you use the above structure to store records in your linked list, then the following code can be used to delete elements from your linked list,
void delitem()
{
info *curr,*prev;
int tdata;
if(head==NULL)
{
cout<<"\nNo Records to Delete!!!";
}
cout<<"\nEnter the Data to be deleted: ";
cin>>tdata;
prev=curr=head;
while((curr!=NULL)&&(curr->data!=tdata))
{
prev=curr;
curr=curr->next;
}
if(curr==NULL)
{
cout<<"\nRecord not Found!!!";
return;
}
if(curr==head)
{
head=head->next;
cout<<"\nData deleted: "<<tdata;
}
else
{
prev->next=curr->next;
if(curr->next==NULL)
{
temp=prev;
}
cout<<"\nData deleted: "<<tdata;
}
delete(curr);
}

I think it is too simple and easy to delete a node or insert ine in linked-list but it requires precise understanding of its MECHANISM. this example shows how to add and remove nodes however it is not a full program but it reveals the mechanism of adding and deleting and moving alinked-list:
#include <iostream>
using namespace std;
//class Data to store ages. in a real program this class can be any other
//class for example a student class or customer...
class Data
{
public:
Data(int age):itsAge(age){}
~Data(){}
void SetAge(int age){itsAge=age;}
int getAge()const{return itsAge;}
private:
int itsAge;
};
//the most important part of the program is the linked0list
class Node
{
public:
//we just make itsPtrHead when created points to Null even if we pass a pointer to Data that is not NULL
Node(Data* pData): itsPtrData(pData),itsPtrHead(NULL),itsCount(0){}
Data* getPdata()const;
Node* getPnext()const;
int getCount()const{return itsCount;}
void insertNode(Data*);//import bcause it shoes the mechanism of linked-list
void deleteNode(int);//most significant in this program
Data* findData(int&,int);
void print()const;
private:
Data* itsPtrData;
Node* itsPtrHead;
int itsCount;
};
Data* Node::getPdata()const
{
if(itsPtrData)
return itsPtrData;
else
return NULL;
}
Node* Node::getPnext()const
{
return itsPtrHead;
}
void Node::insertNode(Data* pData)
{
Node* pNode=new Node(pData);//create a node
Node* pCurrent=itsPtrHead;//current node which points first to the first node that is the "head bode"
Node* pNext=NULL;//the next node
int NewAge=pData->getAge();//the new age that is past to insertNode function
int NextAge=0;//next age
itsCount++;//incrementing the number of nodes
//first we check wether the head node "itsPtrHead" points NULL or not
//so if it is null then we assign it the new node "pNode" and return from insert function
if(!itsPtrHead)
{
itsPtrHead=pNode;
return;
}
//if the condition above fails (head is not null) then check its value and
//compare it with new age and if the new one is smaller than the head
//make this new one the head and then the original node that head points to it make it its next node to the head
if(itsPtrHead->getPdata()->getAge() > NewAge)
{
pNode->itsPtrHead=itsPtrHead;
itsPtrHead=pNode;
//exit the function
return;
}
//if the condition above fails than we move to the next node and so on
for(;;)
{
//if the next node to the current node is null the we set it with this new node(pNode) and exit
if(!pCurrent->itsPtrHead)
{
pCurrent->itsPtrHead=pNode;
return;
}
//else if it not null(next node to current node)
//then we compare the next node and new node
pNext=pCurrent->itsPtrHead;
NextAge=pNext->getPdata()->getAge();
//if next node's age is greater than new then we want new node
//to be the next node to current node then make the original next to current to be the next to its next
if(NextAge > NewAge)
{
pCurrent->itsPtrHead=pNode;
pNode->itsPtrHead=pNext;
//exitting
return;
}
//if no condition succeeds above then move to next node and continue until last node
pCurrent=pNext;
}
}
// delete a node is a bit different from inserting a node
void Node::deleteNode(int age)
{
//deleting a node is much like adding one the differecne is a bit trickier
Node* pTmp=itsPtrHead;
Node* pCurrent=itsPtrHead;
Node* pNext=NULL;
//1 checking for wether age (node contains age) to be deleted does exist
for(;pTmp;pTmp=pTmp->itsPtrHead)
{
if(pTmp->getPdata()->getAge() == age)
break;
}
//if age to be deleted doesn't exist pop up a message and return
if(!pTmp)
{
cout<<age<<": Can't be found!\n";
return;
}
int NextAge=0;
for(;;)
{
//if age to be deleted is on the head node
if(itsPtrHead->getPdata()->getAge() == age)
{
//store the next to head node
pTmp=itsPtrHead->itsPtrHead;
//delete head node
delete itsPtrHead;
//assign the head new node (node after the original head)
itsPtrHead=pTmp;
//decrement the count of nodes
itsCount--;
//exiting gracefully
return;
}
//moving to next node
pNext=pCurrent->itsPtrHead;
NextAge=pNext->getPdata()->getAge();
//checking next node age with age to be deleted. if they
//match delete the next node
if(NextAge == age)
{
//next node holds the target age so we want its NEXT node
//and store it in pTmp;
pTmp=pNext->itsPtrHead;//Next node of the target node
//pCurrent doesn't yet hold the target age but it is the
//previous node to target node
//change the next node of pCurrent so that it doesn't
//point to the target node but instead to the node right
//after it
pCurrent->itsPtrHead=pTmp;
//delete the target node (holds the target age)
delete pNext;
//decrement number of nodes
itsCount--;
//exit
return;
}
//if pNext doesn't point to target node move to the next node
//by making pCurrent points to the next node in the list
pCurrent=pNext;
}
}
void Node::print()const
{
Node* pTmp=itsPtrHead;
while(pTmp)
{
cout<<"age: "<<pTmp->getPdata()->getAge()<<endl;
pTmp=pTmp->itsPtrHead;
}
}
int main()
{
//note this is not a real proram just we show how things works
Data* pData=new Data(6);
Node theNode(pData);
theNode.print();
pData=new Data(19);
theNode.insertNode(pData);
pData=new Data(20);
theNode.insertNode(pData);
pData=new Data(23);
theNode.insertNode(pData);
pData=new Data(25);
theNode.insertNode(pData);
pData=new Data(30);
theNode.insertNode(pData);
pData=new Data(27);
theNode.insertNode(pData);
pData=new Data(33);
theNode.insertNode(pData);
pData=new Data(18);
theNode.insertNode(pData);
theNode.print();
cout<<endl<<endl;
//int age;
//int index;
//cout<<"Age to finde: ";
//cin>>age;
//cout<<endl;
//theNode.Find(index,age);
//cout<<age<<" : Found on index: "<<index<<endl;
//theNode.modify(age);
//theNode.print();
int age;
cout<<"age to delete: ";
cin>>age;
cout<<endl;
theNode.deleteNode(age);
theNode.print();
cout<<endl<<endl<<endl;
return 0;
}
//modify and other member functions are not the purpose of this program

void Delete()
{
int num;
cout<<"enter node to delete"<<endl;
cin>>num;
node *nodeptr=head;
node *prev;
if(head==0)
{
cout<<"list is empty"<<endl;
}
else if(head->data==num)
{
node *t=head;
head=head->next;
delete t;
}
else
{
nodeptr=head;
prev=head;
while(nodeptr!=NULL)
{
if(nodeptr->data==num)
{
prev->next=nodeptr->next;
node *tem=nodeptr->next;
delete tem;
}
prev=nodeptr;
nodeptr=nodeptr->next;
}
}
}

Related

How to remove duplicate entries in a linked list input?

I am tasked with removing all duplicate entries in the linked list. Assuming the list is ordered from smallest to largest, therefore all I need to do is remove the duplicates next to each other.
For example: If the list contains {1,2,2,2,3,3,4,5,5,5,5,5,6} before calling remove_duplicates(), it should contain{1,2,3,4,5,6} after.
My problem is that my code will print the duplicates as well whenever remove_duplicates() is called.
Here is my code:
list.cpp:
#include <iostream>
using namespace std;
#include "list.h"
// on some machines member variables are not automatically initialized to 0
List::List()
{
m_head = NULL;
m_length = 0;
}
// delete all Nodes in the list
// since they are dynamically allocated using new, they won't go away
// automatically when the list is deleted
// Rule of thumb: destructor deletes all memory created by member functions
List::~List()
{
while (m_head)
{
Node *tmp = m_head;
m_head = m_head->m_next;
delete tmp;
}
}
// always insert at the front of the list
// Note: this works even in the SPECIAL CASE that the list is empty
void List::insert(int value)
{
if (!m_head || value < m_head->m_value)
{
m_head = new Node(value, m_head);
}
else
{
Node *ptr = m_head;
while (ptr->m_next != NULL && value > ptr->m_next->m_value)
{
ptr = ptr->m_next;
}
ptr->m_next = new Node(value, ptr->m_next);
}
m_length++;
}
// iterate through all the Nodes in the list and print each Node
void List::print()
{
for (Node *ptr = m_head; ptr; ptr = ptr->m_next)
{
cout << ptr->m_value << endl;
}
}
void List::remove_duplicates()
{
Node *curr = m_head;
Node *temp = m_head;
Node *delPtr = NULL;
if(curr == NULL)
{
return;
}
if(curr != NULL)
{
if(curr -> m_value == curr ->m_next ->m_value)
{
delPtr = curr;
curr = curr -> m_next;
temp ->m_next = curr;
delete delPtr;
}
else
{
curr = curr -> m_next;
}
}
}
list.h:
class List
{
public:
List();
~List();
void insert(int value); // insert at beginning of list
void print(); // print all values in the list
int length() {return m_length;}
void remove_duplicates();
int *convert_to_array(int &size);
private:
class Node
{
public:
Node(int value, Node *next)
{m_value = value; m_next = next;}
int m_value;
Node *m_next;
};
Node *m_head;
int m_length;
};
main.cpp:
#include <assert.h>
#include <iostream>
using namespace std;
#include "list.h"
int main()
{
List list;
int value;
// read values and insert them into list
while (cin >> value)
{
list.insert(value);
}
cout << "printing original list: \n";
list.print();
list.remove_duplicates();
cout << "printing list after removing duplicates: \n";
list.print();
}
Note: Everything has been given to me by my instructor, the only code that I am supposed to write is void List::remove_duplicates()
I have looked up other examples on stackoverflow, but none seem to help me with my situation.
Also, I do want to mention that I am still very new to Linked Lists and how they function. Therefore I am not exactly sure where to go from here. Any help would be appreciated
You need to iterate over your list using both the Address of the current pointer, and the current pointer. See Linus on Understanding Pointers. Since you don't just want to delete a node with a certain value, but you want to scan forward in the list deleting ALL nodes with that value, you want to loop over each node, and within the loop scan-forward deleting ALL nodes with the value of the current node.
You do that by checking the m_next->m_value and if it the same as the current node value, you REPLACE the node at the current pointer ADDRESS with the next node content. Since you still have a pointer to the node you have replaced, you can simply delete that node and then update the pointer from the address of the current node.
This presumes your list is in SORT-ORDER as you show in your question. If it isn't, you would need to scan the list multiple times. In sort-order as shown, you could do:
/* list must be in sort order */
void List::remove_duplicates()
{
Node **pp = &m_head, /* current address of head (pointer-to-pointer) */
*p = m_head; /* pointer to head */
/* loop over each node */
for (; p; pp = &p->m_next, p = p->m_next) {
/* while m_next and current value == next value */
while (p->m_next && (*pp)->m_value == p->m_next->m_value)
{
*pp = p->m_next; /* set node at current address to next node */
delete p; /* delete original node at that address */
p = *pp; /* update pointer to current node address */
}
}
}
(essentially if the current node and next have the same m_value you are throwing away the current node (and properly deleting the memory) and replacing it with the next)
Then for example, if your list originally contained:
0 0 1 1 1 2 3 4 4 5 6 6 6 7 8 9 9 9
calling list.remove_duplicates() would result in:
0 1 2 3 4 5 6 7 8 9
Look things over and let me know if you have further questions.

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!

Unable to figure out how to delete the entire Linked List through a function using classes only

Being a beginner for C++, I was able to get to the point of making a linkedlist using classes and not templates or vectors, and reached to a point where i can ad a node to the end, delete a node from the end (by value) and print the node. However, I now want to know how to be able to clear the complete set of nodes thereby clearing the complete linkedlist, without using any specialized functions or special headers.
I went through the following resources of reference but could not set or align my understanding with them as the following sources have done using different methods:-
Can't figure out how to clear a linked list in c++?
Linked List Delete Method
(yes i tried getting ideas from java even though i dont know java but just tried too)
C programming Linked Lists delete node at position N
How would I clear a linked list? (came closest to make me understand it but some confusion)
Book: Deitel and Deitel (surprisingly near to my thought only that they have shown using templates or vectors)
Book: Primer (a little bit hard for me to understand)
Any help would be highly appreciated. Please try and forgive some of my bad habbits of programming like using namespace std and etc, etc, as my aim is to get the DeleteAll function working(clearing the complete list), look at the block of code which is commented totally in the last function of the class LinkedList.
Then look at the Case 4 where i am trying to call it in the main function.this my first time with the concept of linked list, and yes it seems very intimidating.
#include <iostream>
#include <cstdlib>
#include "ctype.h" //for enabling the recognition of data types for different illegal user inputs for main program
using namespace std;
// Node class
class Node
{
int data;
Node* next;
public:
Node(){};
void setData(int aData)
{
data = aData;
}
void setNext(Node* aNext)
{
next = aNext;
}
int Data()
{
return data;
}
Node* Next()
{
return next;
}
};
// LinkedList Class
class LinkedList
{
private:
Node *head;
public:
List()
{
head = NULL;
}
// printing contents of list
void Print()
{
Node *tmp = head;
// but if no Nodes then following
if (tmp==NULL)
{
cout<<"\n \t\tcannot find any Nodes: List EMPTY\n";
return;
}
//if one node is found
else if (tmp->Next()==NULL)
{
cout<<tmp->Data();
cout<<"-->";
cout<<"NULL"<<endl;
}
//else more nodes then parse and print the list
else
{
do
{
cout<<tmp->Data();
cout<<"-->";
tmp = tmp->Next();
}
while(tmp!=NULL);
cout<<"";
cout<<"X"<<endl;
}
}
//Append or add a node to the linked list
void Append(int data)
{
//creates a new node;
Node *newNode = new Node();
newNode->setData(data);
newNode->setNext(NULL);
//create a temp pointer for further linking to be facilitated
Node *tmp = head;
//but before setting next link to point last node to new node
//we need to check if we are at the end of the list and if not then traverse to the end of node
if(tmp !=NULL)
{
while(tmp->Next() !=NULL)
{
tmp = tmp->Next();
}
tmp->setNext(newNode);
}
else
{
head = newNode;
}
}
//Delete a node from list BY VALUE
void Delete(int data)
{
//again create a temp pointer.
Node *tmp = head;
//again if no nodes
if (tmp==NULL)
{
cout<<"\n \t\tNo Nodes to delete\n";
return;
}
//Last node in the list which is the same as only one node left in list then following
else if(tmp->Next()==NULL)
{
delete tmp;
head = NULL;
}
//again parse through the nodes again to delete the data related node.
else
{
Node *prev;
do
{
if(tmp->Data()==data)
{
break;
}
else
{
prev = tmp;
tmp = tmp->Next();
}
}
while(tmp != NULL);
//once the data is found and located then readjust the linkage of previous with next and
//delete the current node
prev->setNext(tmp->Next());
delete tmp;
}
}
//
// int Deleteall()
// {
// again create a temp pointer.
// Node *tmp = head;
//
//
// again if no nodes
// if (tmp==NULL)
// {
// cout<<"\n \t\tNo Nodes to delete\n";
// return 0;
// }
//
// Last node in the list which is the same as only one node left in list then following
// else if(tmp->Next()==NULL)
// {
// delete tmp;
// head = NULL;
// }
//
// again parse through the nodes again to delete the data related node.
// else
// {
// Node *prev;
//
// while(tmp);
// {
//
// once the data is found and located then readjust the linkage of previous with next and
// delete the current node
// prev->setNext(tmp->Next());
// delete tmp;
// }
// } return 0;
// }
};
//Now call through the main function
int main()
{
//New List
LinkedList list1;
int usrdata, choice;
while(choice)
{
cout<<"\n\nPlease choose an action to be performed on the LinkedList\n\ninput 1 for adding/appending a node\ninput 2 for printing the list\ninput 3 for deleting the node by value\ninput 4 to exit\n\n";
cin>>choice;
switch(choice)
{
case 1 :
cout<<"\nEnter your desired data for adding/appending\n";
cin>>usrdata;
list1.Append(usrdata);
list1.Print();
continue;
case 2 :
cout<<"\nPrinting\n";
list1.Print();
break;
case 3 :
cout<<"\nEnter your desired data for removal/deleting\n";
cin>>usrdata;
list1.Delete(usrdata);
list1.Print();
break;
case 4 :
cout<<"\n deleting n exiting...\n";
// list1.Deleteall();
list1.Print();
goto end;
default :
cout<<"I think you should go home now you seem tired\n";
}
}
end:
cout<<"\n\nThis statement was reached because either you chose to exit or entered a wrong/illegal value or operation\n\n";
system("pause");
return 0;
}
How to get the last function (completely commented lines) DeleteAll working to clear the entire list without using any other specialized headers or special functions etc.
Delete all is actually a simple process.
Here is the algorithm:
current node is head
while the current node is not null
get the next node
delete the current node
current node is next node
set head to null
You don't have to worry about maintaining links as you are removing everything.

"lvalue required as left operand of assignment" error writing a linked list

I am currently learning some C++ for a course I am taking in school. I have basic understanding of lvalues and rvalues, but I am unable to determine why I am receiving a compiler error.
I am creating a singly linked list and need to be able to reverse it. As per my assignment I have two classes. The first is the node and just holds an int as well as a pointer.
class Node {
int data;
Node *next;
public:
//Constructor
Node(int d) {
data = d;
next = NULL;}
//Set to next Node
void SetNext(Node *nextOne) {
next = nextOne;}
//Returns data value
int Data(){return data;}
//Returns next Node
Node *Next() {return next;}
};
Then I have a linked list class that has a header pointer and then a number of functions for adding, printing etc. the list.
class LinkedList {
Node *head;
public:
//Constructor
LinkedList(){head = NULL;}
void AddNode(int d) {
//Create a new Node
Node *newNode = new Node(d);
//Create a temporary pointer
Node *temp = head;
//If there are already nodes in the list
if(temp != NULL) {
//Parse through to the end of the list
while(temp->Next() != NULL) {
temp = temp->Next();}
//Point the last Node in the list to the new Node
temp->SetNext(newNode);
}
//If adding as the first Node
else{
head = newNode;}
}
void PrintList() {
//Temporary pointer
Node *temp = head;
//If there are no nodes in the list
if(temp == NULL) {
std::cout << "The list is empty" << std::endl;}
//If there is only one node in the list
if(temp->Next() == NULL) {
std::cout << temp->Data() << std::endl;}
//Parse through the list and print
else {
do {
std::cout << temp->Data();
temp = temp->Next();
}
while(temp != NULL);
}
}
//Returns the number of nodes in the list
int CountList() {
//Temporary pointer
Node *temp = head;
//Counter variable
int counter = 0;
//If the list is empty
if(temp == NULL) {
return counter;}
//Parse through Nodes counting them
else {
do {counter++;
temp = temp->Next();
}
while(temp != NULL);
}
return counter;
}
//Reverses the list
Node *ReverseList() {
//Initially set to NULL then tracks the new head
Node *marker = NULL;
//Tracks the next one in the list
Node *nextOne;
//Sets the first Node to NULL and then sets the last Node to point to
//the first one and rotates through the list pointing the last to the
//first
while(head != NULL) {
nextOne = head->Next();
head->Next() = marker;
marker = head;
head = nextOne;
}
//Setting the head back to the start again
head = marker;
}
};
One of those functions is supposed to reverse the list. The line "head->Next() = marker;" in the ReverseList function is causing a "lvalue required as left operand of assignment" error when compiling.
Any insight as to why this is occurring and how I can correct the problem?
Thank you in advance!
The return from the call to Next() is an rvalue. As you are in a class function, you don't need to call the Next function to get at the private next pointer, you can just use it directly.
head->next = marker;
Your Next() function returns a pointer, and you then do this:
head->Next() = marker;
You're changing the pointer to marker and not what it's pointing at. To solve this you need to dereference that pointer:
*head->Next() = marker;
your signature for next is:
Node *Next() {return next;}
This makes a copy of next pointer at return and hence it is treated as r-value and not l-value.
One way of overcoming this would be to use a pointer-to-pointer:.
Node **Next() {return &next;}
And then use it as:
int main()
{
Node* marker=new Node(89);
Node* nod=new Node(9);
*(nod->Next())= marker;
cout<<(nod->next)->data<<endl;
cout << "Hello World" << endl;
return 0;
}
This makes it more complicated to use.

C++ Linked List assignment: trouble with insertion and deletion

I am working on a linked list implementation in C++. I am making progress but am having trouble getting the insertion functionality and deletion functionality to work correctly. Below is list object in the C++ header file:
#ifndef linkList_H
#define linkList_h
//
// Create an object to represent a Node in the linked list object
// (For now, the objects to be put in the list will be integers)
//
struct Node
{
Node() : sentinel(0) {}
int number;
Node* next;
Node* prev;
Node* sentinel;
};
//
// Create an object to keep track of all parts in the list
//
class List
{
public:
//
// Contstructor intializes all member data
//
List() : m_listSize(0), m_listHead(0) {}
//
// methods to return size of list and list head
//
Node* getListHead() const { return m_listHead; }
unsigned getListSize() const { return m_listSize; }
//
// method for adding and inserting a new node to the linked list,
// retrieving and deleting a specified node in the list
//
void addNode(int num);
void insertNode(Node* current);
void deleteNode(Node* current);
Node* retrieveNode(unsigned position);
private:
//
// member data consists of an unsigned integer representing
// the list size and a pointer to a Node object representing head
//
Node* m_listHead;
unsigned m_listSize;
};
#endif
And here is the implementation (.cpp) file:
#include "linkList.h"
#include <iostream>
using namespace std;
//
// Adds a new node to the linked list
//
void List::addNode(int num)
{
Node *newNode = new Node;
newNode->number = num;
newNode->next = m_listHead;
m_listHead = newNode;
++m_listSize;
}
//
// NOTWORKING: Inserts a node which has already been set to front
// of the list
//
void List::insertNode(Node* current)
{
// check to see if current node already at
// head of list
if(current == m_listHead)
return;
current->next = m_listHead;
if(m_listHead != 0)
m_listHead->prev = current;
m_listHead = current;
current->prev = 0;
}
//
// NOTWORKING: Deletes a node from a specified position in linked list
//
void List::deleteNode(Node* current)
{
current->prev->next = current->next;
current->next->prev = current->prev;
}
//
// Retrieves a specified node from the list
//
Node* List::retrieveNode(unsigned position)
{
if(position > (m_listSize-1) || position < 0)
{
cout << "Can't access node; out of list bounds";
cout << endl;
cout << endl;
exit(EXIT_FAILURE);
}
Node* current = m_listHead;
unsigned pos = 0;
while(current != 0 && pos != position)
{
current = current->next;
++pos;
}
return current;
}
After running a brief test program in the client C++ code, here is the resulting output:
Number of nodes: 10
Elements in each node:
9 8 7 6 5 4 3 2 1 0
Insertion of node 5 at the list head:
4 9 8 7 6 5 4 9 8 7
Deletion of node 5 from the linked list
As you can see, the insertion is not simply moving node 5 to head of list, but is overwriting other nodes beginning at the third position. The pseudo code I tried to implement came from the MIT algorithms book:
LIST-INSERT(L, x)
next[x] <- head[L]
if head[L] != NIL
then prev[head[L]] <- x
head[L] <- x
prev[x] <- NIL
Also the deletion implementation is just crashing when the method is called. Not sure why; but here is the corresponding pseudo-code:
LIST-DELET'
next[prev[x]] <- next[x]
prev[next[x]] <- prev[x]
To be honest, I am not sure how the previous, next and sentinel pointers are actually working in memory. I know what they should be doing in a practical sense, but looking at the debugger it appears these pointers are not pointing to anything in the case of deletion:
(*current).prev 0xcdcdcdcd {number=??? next=??? prev=??? ...} Node *
number CXX0030: Error: expression cannot be evaluated
next CXX0030: Error: expression cannot be evaluated
prev CXX0030: Error: expression cannot be evaluated
sentinel CXX0030: Error: expression cannot be evaluated
Any help would be greatly appreciated!!
You have got an error in addNode(). Until you fix that, you can't expect insertNode to work.
Also, I think your design is quite silly. For example a method named "insertNode" should insert a new item at arbitrary position, but your method insertNode does a pretty different thing, so you should rename it. Also addNode should be renamed. Also as glowcoder wrote, why are there so many sentinels? I am affraid your class design is bad as a whole.
The actual error is that you forgot to set prev attribute of the old head. It should point to the new head.
void List::addNode(int num)
{
Node *newNode = new Node;
newNode->number = num;
newNode->next = m_listHead;
if(m_listHead) m_listHead->prev = newNode;
m_listHead = newNode;
++m_listSize;
}
Similarly, you have got another error in deleteNode(). It doesn't work when deleting last item from list.
void List::deleteNode(Node* current)
{
m_listSize--;
if(current == m_listHead) m_listHead = current->next;
if(current->prev) current->prev->next = current->next;
if(current->next) current->next->prev = current->prev;
}
Now you can fix your so-called insertNode:
void List::insertNode(Node* current)
{
int value = current->number;
deleteNode(current);
addNode(value);
}
Please note that I wrote everything here without compiling and testing in C++ compiler. Maybe there are some bugs, but still I hope it helps you at least a little bit.
In deleteNode, you are not handling the cases where current->next and/or current->prev is null. Also, you are not updating the list head if current happens to be the head.
You should do something like this:
node* next=current->next;
node* prev=current->prev;
if (next!=null) next->prev=prev;
if (prev!=null) prev->next=next;
if (m_listhead==current) m_list_head=next;
(Warning: I have not actually tested the code above - but I think it illustrates my idea well enough)
I am not sure what exactly your InsertNode method does, so I can't offer any help there.
OK.
As #Al Kepp points out, your "add node" is buggy. Look at Al's code and fix that.
The "insert" that you are doing does not appear to be a normal list insert. Rather it seems to be a "move to the front" operation.
Notwithstanding that, you need to delete the node from its current place in the list before you add it to the beginning of the list.
Update
I think you have misunderstood how insert should work. It should insert a new node, not one that is already in the list.
See below for a bare-bones example.
#include <iostream>
// List Node Object
//
struct Node
{
Node(int n=0);
int nData;
Node* pPrev;
Node* pNext;
};
Node::Node(int n)
: nData(n)
, pPrev(NULL)
, pNext(NULL)
{
}
//
// List object
//
class CList
{
public:
//
// Contstructor
//
CList();
//
// methods to inspect list
//
Node* Head() const;
unsigned Size() const;
Node* Get(unsigned nPos) const;
void Print(std::ostream &os=std::cout) const;
//
// methods to modify list
//
void Insert(int nData);
void Insert(Node *pNew);
void Delete(unsigned nPos);
void Delete(Node *pDel);
private:
//
// Internal data
//
Node* m_pHead;
unsigned m_nSize;
};
/////////////////////////////////////////////////////////////////////////////////
CList::CList()
: m_pHead(NULL)
, m_nSize(0)
{
}
Node *CList::Head() const
{
return m_pHead;
}
unsigned CList::Size() const
{
return m_nSize;
}
void CList::Insert(int nData)
{
Insert(new Node(nData));
}
void CList::Insert(Node *pNew)
{
pNew->pNext = m_pHead;
if (m_pHead)
m_pHead->pPrev = pNew;
pNew->pPrev = NULL;
m_pHead = pNew;
++m_nSize;
}
void CList::Delete(unsigned nPos)
{
Delete(Get(nPos));
}
void CList::Delete(Node *pDel)
{
if (pDel == m_pHead)
{
// delete first
m_pHead = pDel->pNext;
if (m_pHead)
m_pHead->pPrev = NULL;
}
else
{
// delete subsequent
pDel->pPrev->pNext = pDel->pNext;
if (pDel->pNext)
pDel->pNext->pPrev = pDel->pPrev;
}
delete pDel;
--m_nSize;
}
Node* CList::Get(unsigned nPos) const
{
unsigned nCount(0);
for (Node *p=m_pHead; p; p = p->pNext)
if (nCount++ == nPos)
return p;
throw std::out_of_range("No such node");
}
void CList::Print(std::ostream &os) const
{
const char szArrow[] = " --> ";
os << szArrow;
for (Node *p=m_pHead; p; p = p->pNext)
os << p->nData << szArrow;
os << "NIL\n";
}
int main()
{
CList l;
l.Print();
for (int i=0; i<10; i++)
l.Insert((i+1)*10);
l.Print();
l.Delete(3);
l.Delete(7);
l.Print();
try
{
l.Delete(33);
}
catch(std::exception &e)
{
std::cerr << "Failed to delete 33: " << e.what() << '\n';
}
l.Print();
return 0;
}