This question already has an answer here:
Deleting the whole Linked List
(1 answer)
Closed 5 months ago.
I have my linked list code:
#include <string>
#include <iostream>
using namespace std;
class Node
{
public:
string name;
int age;
Node *next;
Node(string name, int age)
{
this->name = name;
this->age = age;
this->next = nullptr;
}
};
class List
{
private:
Node *head;
int size;
public:
List()
{
this->head = nullptr;
this->size = 0;
}
void insert(string name, int age)
{
Node *nodenew = new Node(name, age);
nodenew->next = nullptr;
if (this->head == nullptr)
{
this->head = nodenew;
}
else
{
Node *auxi = this->head;
while (auxi->next != nullptr)
{
auxi = auxi->next;
}
auxi->next = nodenew;
}
this->size = this->size + 1;
}
void print()
{
if (this->head == nullptr)
{
cout << "List is empty"<<endl;
}
Node *auxi = this->head;
cout<<to_string(this->size)+" users in the linked list"<<endl;
while (auxi != nullptr)
{
cout << auxi->name << ", " << auxi->age << endl;
auxi = auxi->next;
}
}
};
int main()
{
List linkedList;
linkedList.insert("David", 56);
linkedList.insert("Susan", 25);
linkedList.insert("Kim", 41);
linkedList.insert("Charles", 23);
linkedList.insert("Bob", 20);
linkedList.insert("James", 75);
linkedList.insert("Carl", 36);
linkedList.insert("Andy", 78);
linkedList.print();
return 0;
}
As you can see I did insert method, print method. And now want I want is to delete all nodes in the linkedList object, so I would like to know if there is some way to make for example something like linkedList = nullptr or something similar to delete all data in my linked list.
I tried to make that in the main method:
linkedList = nullptr;
But my compiler shows me this error:
no operator "=" matches these operands
I hope you can help me, thanks.
linkedList = nullptr; won't work, since it makes no sense. linkedList isn't a pointer. It has a pointer inside of it, but it's not itself a pointer. Besides, if that did work, it wouldn't delete the nodes, so it would be a memory leak.
You should create a function empty() (or more usually called clear()) in your List class. Make it so it deletes all the nodes, then sets head to nullptr and size to 0. Then in main(), you can call linkedList.empty(); (or linkedList.clear();)
Related
I am tasked with implementing a new class function called bool List::largest_value(int &largest) within a given class List. The instruction is:
If the list is not empty, put the largest value in the largest
parameter and return true. If the list is empty, return false.
My question is, how do I find the largest value within a parameter?
Here is what I have so far for bool List::largest_value(int &largest):
// Fill in the functions at the bottom of this file
//
#include <iostream>
#include <climits>
using namespace std;
#include "list.h"
// on some machines member variables are not automatically initialized to 0
List::List()
{
m_head = NULL;
}
// 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)
{
m_head = new Node(value, m_head);
}
// 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::compare(int target, int &less_than, int &equal, int &greater_than)
{
Node *temp = m_head;
less_than = 0;
equal = 0;
greater_than = 0;
while(temp != NULL)
{
if(temp->m_value > target)
{
greater_than++;
}
else if(temp->m_value < target)
{
less_than++;
}
else if(temp->m_value == target)
{
equal++;
}
temp = temp-> m_next;
}
}
bool List::largest_value(int &largest)
{
Node *temp = m_head;
largest = INT_MIN;
if(temp == NULL)
{
return false;
}
while(temp != NULL)
{
if(temp->m_value > largest)
{
largest = temp->m_value;
}
temp = temp->m_next;
}
return true;
}
Here is the given class List:
class List
{
public:
List();
~List();
void insert(int value); // insert at beginning of list
void print(); // print all values in the list
void compare(int target, int &less_than, int &equal, int &greater_than);
bool largest_value(int &largest);
private:
class Node
{
public:
Node(int value, Node *next)
{m_value = value; m_next = next;}
int m_value;
Node *m_next;
};
Node *m_head;
};
Main.cpp:
#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);
}
int largest;
bool result = list.largest_value(largest);
if (result == false)
{
cout << "empty list" << endl;
return 1;
}
else
{
cout << "The largest value you entered is: " << largest << endl;
}
}
My code compiles and runs, however I keep receiving the output empty list. I honestly have no idea what I need to change in my bool List::largest_value(int &largest)function. I am still very new to linked lists. Any help would be appreciated
i am simply creating a payroll system that has a employee name and a working hours for that employee.. the data is supposed to be stored in a linked list data structure, but i can not connect the linked list to the object of the class employee, i tried making the pay roll linked list (i.e empList) as a static member so that all the objects of the class can use the same list object and data can be stored but once i compile my code i get an error of "undefined reference to employee::empList" at line 130 that is the last line of constructor, same error on line 150 that is a print pay roll function.. where ever i am trying to call any payRollLinkedList class's function in employee class it gives error.. bottom line is that all i want is to data be stored in a doubly linked list of employees and i can not access the list.
#include <iostream>
using namespace std;
class payRollLinkedList;
class node
{
private:
node* previousPointer;
string name;
int hoursWorked;
node* nextPointer;
friend class payRollLinkedList;
public:
explicit node(const string argName, const int argHoursWorked)
: previousPointer{nullptr}, name{argName}, hoursWorked{argHoursWorked}, nextPointer{nullptr}
{}
};
class payRollLinkedList
{
private:
node* headPointer{nullptr};
node* tailPointer{nullptr};
node* getNewNode(const string argName, const int argHoursWorked)
{
return new node(argName, argHoursWorked);
}
public:
void addAtBack(const string argName, const int argHoursWorked)
{
node* newNode{getNewNode(argName, argHoursWorked)};
if(isEmpty())
{
headPointer = tailPointer = *newNode;
}
else
{
tailPointer->nextPointer = newNode;
newNode->previousPointer = tailPointer;
tailPointer = newNode;
newNode = nullptr;
delete newNode;
}
}
bool deleteNode(string argName)
{
node* currentPointer{headPointer};
if(isEmpty())
{
cout <<"the list is already empty\n";
return false;
}
else
{
while(currentPointer != nullptr)
{
if(currentPointer->name == argName)
{
if(currentPointer == headPointer)
{
node* tempPointer{headPointer};
headPointer = headPointer->nextPointer;
tempPointer->nextPointer = nullptr;
headPointer->previousPointer = nullptr;
delete tempPointer;
break;
}
if(currentPointer == tailPointer)
{
node*tempPointer{tailPointer};
tailPointer = tailPointer->previousPointer;
tempPointer->previousPointer = nullptr;
tailPointer->nextPointer = nullptr;
delete tempPointer;
break;
}
node* tempPointer{currentPointer};
node* nextPtr{tempPointer->nextPointer};
currentPointer = currentPointer->previousPointer;
currentPointer->nextPointer = nextPtr;
nextPtr->previousPointer = currentPointer;
tempPointer->nextPointer = nullptr;
tempPointer->previousPointer = nullptr;
currentPointer = nullptr;
nextPtr = nullptr;
delete tempPointer;
delete currentPointer;
delete nextPtr;
}
else
currentPointer = currentPointer->nextPointer;
}
return true;
}
}
void print()
{
if(isEmpty())
{
cout <<"nothing to show\n";
return;
}
else
{
node* currentPointer{headPointer};
while(currentPointer != nullptr)
{
cout <<currentPointer->name <<"\t";
currentPointer = currentPointer->nextPointer;
}
}
}
bool isEmpty()
{
return headPointer == nullptr? true : false;
}
};
class employee
{
private:
string name;
int hoursWorked;
static payRollLinkedList empList;
public:
employee()
: name{""}, hoursWorked{0}
{}
employee(string argName, int argHoursWorked)
{
name = argName;
hoursWorked = argHoursWorked;
empList.addAtBack(name, hoursWorked);
}
void printPayRoll()
{
empList.print();
}
};
int main()
{
employee emp("usman", 12);
employee emp1("ali", 12);
emp.printPayRoll();
}
https://en.cppreference.com/w/cpp/language/static
You need to define static member of class at global scope (out of class).
i suggest you to split your code .h and .cpp files and define the member in .cpp file.
payRollLinkedList employee::empList;
When I build the code, I don't get any errors in the output window. However, after running it, the compiler throws an exception (I'll comment where it is being thrown) at my code saying "Exception thrown: read access violation.
temp was 0xCDCDCDCD.".
I tried researching what this error is, and I found that this is for unassigned memory, but I don't see where something is being unassigned.
This is my Linked List .cpp file. The exception is thrown at a line towards the end of this file.
#include "linkedlist.h"
struct ll::node
{
weapons data;
node* next;
};
ll::ll()
{
head = NULL;
}
ll::~ll()
{
while (head != NULL)
{
node* temp = head;
head = head->next;
delete temp;
}
}
void ll::addItem(weapons obj)
{
node* newNode = new node;
node* temp = head;
newNode->data = obj;
if (head == NULL)
head = newNode;
return;
while (temp->next != NULL)
{
temp = temp->next;
}
if (temp->next == NULL)
{
temp->next = newNode;
return;
}
}
void ll::displayItems()
{
for (node* temp = head; temp != NULL; temp = temp->next)
{
temp->data.getDescription(); //EXCEPTION THROWN HERE
}
}
This file has the inherited class "Weapons" which is the object that is being called as "temp->data". As well as where I have "getDescription".
#include <vector>
using namespace std;
//base class
class inventory
{
protected:
//number of items in inventory
int mNumItems;
public:
//getters
void displayInv();
int getNumItems();
virtual void getDescription();
};
//weapon class
class weapons : public inventory
{
private:
//name of object
string mName;
//what the object is
string mInfo;
//how much of the object
int mAmount;
//how much damage does it do
double mDamage;
public:
//constructor
weapons();
weapons(string, string, double, int);
//getters
string getName();
void getDescription();
int getAmount();
double getDamage();
string getInfo();
//mutators
void setAmount(int);
};
This is where I define weapons
//weapon class
weapons::weapons()
{
mName = " ";
mInfo = " ";
mDamage = 0.0;
mAmount = 0;
}
weapons::weapons(string name, string info, double dmg, int amt)
{
mName = name;
mInfo = info;
mDamage = dmg;
mAmount = amt;
}
string weapons::getName()
{
return mName;
}
int weapons::getAmount()
{
return mAmount;
}
double weapons::getDamage()
{
return mDamage;
}
string weapons::getInfo()
{
return mInfo;
}
void weapons::getDescription()
{
cout << getName() << ", " << getDamage() << " damage, " << getInfo() << " Amount: " << getAmount() << endl;
}
void weapons::setAmount(int amt)
{
mAmount = amt;
}
Let me know if I need to include anymore files!
I get the expected results, which is for it to describe an item which I have in the Linked List. Unfortunately, my only problem is that this exception is being thrown.
Problem
In
struct ll::node
{
weapons data;
node* next;
};
and
void ll::addItem(weapons obj)
{
node* newNode = new node; // leaks if node not added
node* temp = head;
newNode->data = obj;
if (head == NULL)
head = newNode;
return; // this is a NASTY bug of a different sort. Most of the time
// the function will exit without doing ANYTHING
while (temp->next != NULL)
{
temp = temp->next;
}
if (temp->next == NULL) // the only way out of the above loop is if
// temp->next == NULL. This if is redundant.
{
temp->next = newNode;
return;
}
}
Nothing ever sets newNode->next to a safe value. That allows
while (temp->next != NULL)
{
temp = temp->next;
}
to fail because there are no guarantees that temp->next is ever NULL and the loop goes marching off the end of the list.
Solution
Force next to a safe value.
struct ll::node
{
weapons data;
node* next = NULL;
};
Or a more versatile version
struct ll::node
{
weapons data;
node* next;
node(const weapons & weap, // const reference eliminates a possible copy
node * link = NULL): // if you know what the next link will be,
// you can add it here. If not, it's always NULL
data(weap),
next(link)
{
}
};
addItem now looks something like
void ll::addItem(const weapons & obj)
{
if (head == NULL)
{
head = new node(obj); // only making node if we need it
// less chance of leak
}
else
{
node * temp = head;
while (temp->next != NULL)
{
temp = temp->next;
}
temp->next = newNode(obj);
}
}
But you can do something really sneaky here to make life easier. head is really a next pointer by another name, so if you can abstract the different name... And we can by tracking a pointer to next rather than a pointer to the node. This is really handy when you have to insert or remove an item: You have a reference both to the node in question and the insertion point in the previous node.
void ll::addItem(const weapons & obj)
{
node ** temp = &head; // get pointer to insertion point
while ((*temp) != NULL) // next node, including head, is not null
{
temp = &(*temp)->next; // get pointer to next insertion point
}
*temp = newNode(obj); // insert node
}
Half the code. Example of how this helps remove:
void ll::removeItem(const weapons & obj)
{
node ** temp = &head;
while ((*temp) != NULL && (*temp)->data != obj)
{
temp = &(*temp)->next;
}
if (*temp != NULL) // found it!
{
node * rem = *temp; // get node to remove so we don't lose it when we relink
*temp = rem->next; // point at item after rem
delete rem; // release item
}
}
For an exercize, I want to print out a tree data structure that is based on Node objects. This means, every object has a vector nodes that again holds other objects of type Node. But for some reason, when I let print out this->get_nr_children of the leaf nodes which basically just returns nodes.size(), I get completely random (negative) Integers where it should actually return 0. The even more interesting part: Every time I compile and execute, it prints out different Integers that alway are some low negative numbers. I do not have a clue what is happening!
Node.h
#include <string>
#include <vector>
using namespace std;
class Node
{
public:
virtual ~Node();
Node(string name = "");
string get_name() const;
void set_name(string& new_name);
int get_nr_children() const;
Node* get_child(int i) const;
void add_child(Node child);
void create_complete_tree(int nr_child_nodes, int tree_depth);
void print();
private:
string name;
static int node_id;
vector<Node> nodes = {};
};
Node.cpp
#include "node.h"
#include <sstream>
using namespace std;
Node::Node(string name) {
node_id++;
nodes = {};
if (name == "") {
stringstream str_sm;
str_sm << (node_id);
string node_id_str = str_sm.str();
this->name = "node_" + node_id_str;
} else {
this->name = name;
}
}
Node::~Node() {
nodes.clear();
// node_id = 0;
}
int Node::node_id = 0;
string Node::get_name() const {
return name;
}
void Node::set_name(string& new_name) {
this->name = new_name;
}
int Node::get_nr_children() const {
return nodes.size();
}
Node* Node::get_child(int i) const {
if (i >= nodes.size()) {
return NULL;
}
Node node = nodes[i];
Node *ptrNode = &node;
return ptrNode;
}
void Node::add_child(Node child) {
nodes.push_back(child);
}
void Node::create_complete_tree(int nr_child_nodes, int tree_depth) {
tree_depth--;
if (tree_depth <= 0) {
return;
}
for (int i = 0; i < nr_child_nodes; i++) {
Node* node = new Node();
this->add_child(*node);
node->create_complete_tree(nr_child_nodes, tree_depth);
}
}
void Node::print() {
cout << this->get_name() << "\n";
cout << "I got this many children " << this->get_nr_children();
for (int i = 0; i < this->get_nr_children(); i++) {
cout << "\t";
this->get_child(i)->print();
cout << "\n";
}
}
main.cpp
#include <iostream>
#include "node.cpp"
using namespace std;
int main() {
Node* root = new Node("root");
Node* left_child = new Node("left child");
Node* right_child = new Node("right child");
root->add_child(*left_child);
root->add_child(*right_child);
root->print();
return 0;
}
When I execute it I get:
root I got this many children 2 left child I got this many children
-62802357 right child I got this many children -62802357
Process finished with exit code 0
Your problem stems from
this->get_child(i)->print();
get_child returns a pointer to a local object. That object is destroyed when the function returns so the call to print on that returned Node is working with an already destroyed Node.
What you need to do is return a pointer directly to the vector element like
Node* Node::get_child(int i) /*const*/ { // cant be const for the return
if (i >= nodes.size()) {
return NULL;
}
return &nodes[i];
}
Node* Node::get_child(int i) const {
if (i >= nodes.size()) {
return NULL;
}
Node node = nodes[i];
Node *ptrNode = &node;
return ptrNode;
}
Above you return a pointer to destroyed local Node node after get_child(i) returned. Correct code is below, that returns a pointer to a child in the vector.
Node* Node::get_child(int i) const {
if (i >= nodes.size()) {
return NULL;
}
return &nodes[i];
}
main could be implemented much easier without pointers and memory leaks.
int main() {
Node root("root");
root.add_child(Node("left child"));
root.add_child(Node("right child"));
root.print();
return 0;
}
The problem is with the function Node* Node::get_child(int i) const. It returns a pointer to an object that is destroyed by the end of the function call.
Node* Node::get_child(int i) const {
if (i >= nodes.size()) {
return NULL;
}
Node node = nodes[i]; // <- node is a copy of nodes[i]
Node *ptrNode = &node;
return ptrNode; // <- returns a pointer to node
} // <- local objects are destroyed, including node
You must return a pointer to the actual element from the vector.
Node* Node::get_child(int i) const {
if (i >= nodes.size()) {
return NULL;
}
return &nodes[i]; // <- Returns the address of the actual node
}
So I am trying to improve this code in c++. What this does it creates two classes: Student and Studentlist. Any suggestions on improving the linked list data structure here will be greatly appreciated.
#include <iostream>
using namespace std;
//declaring a class student
class Student
{
public:
char *RollNo;
Student *next;
//function student that includes arguments roll number and a pointer poniting to next node student
Student(char *rollNo, Student *Next)
{
this->RollNo = rollNo;
this->next = Next;
}
//fucntion to get roll number
char* getRollNo()
{
return RollNo;
}
//function to get the pointer to next node named student
Student *getNext()
{
return next;
}
void setNext(Student *aNode)
{
this->next = aNode;
}
};
//declareing a class StudentList
class StudentList
{
public:
Student *head;
// default constructor
StudentList()
{
head = NULL;
}
void Add(char *aRollNo)
{
Student *newStudent = new Student(aRollNo, NULL);
Student *temp = head;
if (temp != NULL)
{
while (temp->getNext() != NULL)
{
temp = temp->getNext();
}
temp->setNext(newStudent);
}
else
{
head = newStudent;
}
}
void display()
{
Student *temp = head;
if (temp == NULL)
{
cout << "no student data in the Student List" << endl;
return;
}
if (temp->getNext() == NULL)
{
cout << temp->getRollNo();
}
else
{
do
{
cout << temp->getRollNo() << " --next--> ";
temp = temp->getNext();
} while (temp != NULL);
cout << " end --> null" << endl;
}
}
};
main()
{
StudentList list;
list.Add("My Roll Number is 411\n");
list.display();
cout << "--------------------------------\n";
system("pause");
return 0;
}
The declaration of main() is not complete.
main()
See What is the proper declaration of main?
Also literal strings have a type of char const*. So your method call Add("XXX") has no matching point in the class. The closest you have is Add(char*) which does not match the const part.
Personally I would avoid using C-Strings in C++. You should look at using std::string to handle strings of characters it will avoid many problems.
while you are always add at the last i recomended you to replace your Add algorithm code with this
Student* Add(char *aRollNo,Student* last)
{
Student *newStudent = new Student(aRollNo, NULL);
Student *temp = last;
if (head == NULL){
head=newStudent;
temp=head;}
else
temp=temp->setNext(newStudent);
return temp;
}