Linked list in a class is not removing an element - c++

#include <iostream>
#include <vector>
#include <algorithm>
#include <string>
using namespace std;
struct Node
{
int x;
Node* next = nullptr;
};
typedef Node* nodeptr;
class L
{
private:
nodeptr head = nullptr;
int lengthCount = 0;
public:
void add(const int data);
void print();
void find(const int data);
void pop(const int data);
void listSize();
};
void L:: listSize()
{
cout << "The size of the link list is: " << lengthCount << endl;
}
void L::add(const int data)
{
lengthCount += 1;
Node* newNode = new Node;
newNode->x = data;
if(head == nullptr)
{
head = newNode;
}
else
{
nodeptr temp = head;
while(temp->next != nullptr)
{
temp = temp->next;
}
temp->next = newNode;
}
}
void L::pop(const int data)
{
if(head == nullptr)
{
cout << "Empty List" << endl;
}
else if(head->x == data)
{
head = head->next;
}
else
{
nodeptr temp = head->next;
while(temp != nullptr)
{
if(temp-> x != data)
{
temp = temp->next;
}
else
{
if(temp->next != nullptr)
{
temp = temp->next;
}
else
{
temp->next = nullptr;
}
break;
}
}
}
}
void L::find(const int data)
{
if(head == nullptr)
{
cout << "Empty List" << endl;
}
else
{
nodeptr temp = head;
for(temp; temp != nullptr; temp = temp->next)
{
if(temp->x == data)
{
cout << "Found" << endl;
break;
}
if(temp->next == nullptr)
cout << "Not Found" << endl;
}
}
}
void L::print()
{
nodeptr temp = head;
string line(20,'-');
cout << "Print list" << endl;
cout << line << endl;
while(temp != nullptr)
{
cout << temp->x << endl;
temp = temp->next;
}
cout << line << endl;
}
int main()
{
vector <int> val;
for(int i = 0; i < 10; i++)
val.push_back(5*i);
cout << "Printing list" << endl;
for(auto i : val)
cout << i << " ";
cout << endl;
L listObj;
cout << "Adding list" << endl;
for(auto i : val)
listObj.add(i);
listObj.print();
listObj.listSize();
listObj.find(15);
listObj.print();
cout << "popping 10" << endl;
listObj.pop(10);
listObj.print();
}
The problem that I am having is, I am not able to modify the actually memory of a linked list while using a class.
Im not sure what did I do wrong.
If adding works, i would say the idea of removing a value should work as well.
the remove function is called pop.
the pop function is not removing the value 10, so i am not sure why.
If it is a function that is not in a class, i would say i need to pass a head pointer with & operator then i can actually modify the value.
Please let me know where did I do wrong.
Thanks

Your pop method is not correct, You also have to link the current node with the previous next. It should be like this
void L::pop(const int data)
{
if(head == nullptr)
{
cout << "Empty List" << endl;
}
else if(head->x == data)
{
nodeptr temp = head;
head = head->next;
delete temp;
}
else
{
nodeptr temp = head->next;
nodeptr prev = head;
while(temp != nullptr)
{
if(temp-> x != data)
{
prev = temp;
temp = temp->next;
}
else
{
if(temp->next != nullptr)
{
prev -> next = temp -> next;
delete temp;
}
else
{
delete temp;
prev -> next = nullptr;
}
break;
}
}
}
}

You need to keep track of the "previous" node of the linked list somehow. There's many ways to do it, but the clearest might be:
void L::pop(const int data) {
if(head == nullptr) {
cout << "Empty List" << endl;
return;
}
if(head->x == data) {
node *temp = head;
head = head->next;
delete temp;
return;
}
int *prev = head;
int *temp = head->next;
while (temp != null) {
if (temp->x != data) {
prev = prev->next;
temp = temp->next;
} else {
prev->next = temp->next;
delete temp;
return;
}
}
}

In addition to the answers given already there's a variant without having to track the previous element all the time:
for(Node* tmp = head; tmp->next; tmp = tmp->next;)
{
if(tmp->next->x == data)
{
// OK, one intermediate pointer we need anyway, but we need it
// only once
Node* del = tmp->next;
tmp->next = tmp->next->next;
delete del;
break;
}
}
The for loop as a little bonus is a bit more compact, but that's just a matter of personal taste.

Related

How to resolve "Unhandled exception thrown: read access violation." for reverse linked list?

I am working on reverse linked list on Windows 10 Pro (64 bit) with Visual Studio Community 2019. I would like to know how to resolve the error I get as below. I get below error in the while loop in the member function reverse() in the class List
(*Please assume the list is already prepared like contiguous integer e.g. 0,1,2,3,4,5)
Could you please anyone give me some advice? Thank you in advance.
Unhandled exception thrown: read access violation.
current was 0xDDDDDDDD.
#include <iostream>
#include <string.h>
#include <vector>
using std::cout;
using std::endl;
template <class Data>
class Node
{
public:
Node* next;
Data data;
};
template <class Data>
class List
{
private:
Node<Data>* head;
Node<Data>* tail;
int count;
public:
//constructor
List()
{
count = 0;
head = nullptr;
tail = nullptr;
}
int size()
{
return count;
}
void msg_empty_list()
{
cout << "The list is not modified since it is empty." << endl;
}
int push_back(Data data)
{
Node<Data>* node = new Node<Data>;
node->data = data;
node->next = nullptr;
if (head == nullptr)
{
head = node;
tail = node;
}
else if (head != nullptr)
{
tail->next = node;
tail = tail->next;
}
count++;
return count;
}
int push_front(Data data)
{
Node<Data>* node = new Node<Data>;
node->data = data;
node->next = nullptr;
if (head == nullptr)
head = node;
else if (head != nullptr)
{
node->next = head;
head = node;
}
count++;
return count;
}
int pop_front(void)
{
if (head == nullptr)
return -1;
else if (head != nullptr)
{
Node<Data>* temp;
temp = head;
head = head->next;
delete temp;
count--;
return count;
}
}
int pop_back(void)
{
if (head == nullptr)
return -1;
else if (head != nullptr)
{
Node<Data>* temp = head;
while (temp->next != tail)
temp = temp->next;
delete tail;
tail = temp;
count--;
return count;
}
}
int remove_at(int index)
{
if (head == nullptr)
return -1;
else if (head != nullptr)
{
cout << "Specified index = " << index << endl;
if (index == 0)
{
pop_front();
}
else if (index == -1)
{
pop_back();
}
Node<Data>* temp = head;
Node<Data>* rmv;
int countIndex = 0;
while (countIndex < index - 1)
{
temp = temp->next;
countIndex++;
}
rmv = temp->next;
temp->next = temp->next->next;
delete rmv;
count--;
return count;
}
}
void reverse()
{
Node<Data>* temp = nullptr;
Node<Data>* prev = nullptr;
Node<Data>* current = head;
while (current != nullptr)
{
temp = current->next; // where I get error "Unhandled exception thrown: read access violation. **current** was 0xDDDDDDDD."
current->next = prev;
prev = current;
current = temp;
}
head = prev;
}
void print()
{
Node<Data>* temp = head;
if (head == nullptr)
return;
for (int i = 0; i < count - 1; i++)
{
cout << temp->data << ", ";
temp = temp->next;
}
cout << temp->data;
}
~List()
{
Node<Data>* temp = head;
while (temp->next != nullptr)
{
temp = temp->next;
delete head;
head = temp;
}
}
};
int main()
{
Node<int> x;
Node<bool> y;
Node<char> n;
List<int> list;
//insert items into list
for (int i = 0; i < 10; i++)
{
list.push_back(i);
}
cout << "Original list[size=" << list.size() << "]: ";
//print the list
list.print();
cout << endl;
// push a node to the beginning of the list
cout << endl << "==> Push a node to the head" << endl;
list.push_front(-1);
cout << "Modified list[size=" << list.size() << "]: ";
list.print();
cout << endl;
// pop the head of the list
cout << endl << "==> Pop a node from the head" << endl;
if (list.size() == 0)
list.msg_empty_list();
else
{
list.pop_front();
cout << "Modified list[size=" << list.size() << "]: ";
list.print();
cout << endl;
}
/*
// pop the tail of the list
cout << endl << "==> Pop a node from the tail" << endl;
if (list.size() == 0)
list.msg_empty_list();
else
{
list.pop_back();
cout << "Modified list[size=" << list.size() << "]: ";
list.print();
cout << endl;
}
*/
// delete the node at the specified index
cout << endl << "==> Delete the node at the specified index" << endl;
if (list.size() == 0)
list.msg_empty_list();
else
{
list.remove_at(5);
cout << "Modified list[size=" << list.size() << "]: ";
list.print();
cout << endl;
}
// reverse the list
cout << endl << "==> Reverse the list" << endl;
if (list.size() == 0)
list.msg_empty_list();
else
{
list.reverse();
cout << "Modified list[size=" << list.size() << "]: ";
list.print();
cout << endl;
}
return 0;
}
I can spot a few mistakes in your code, but let's concentrate on the pop_back() function:
int pop_back(void)
{
if (head == nullptr)
return -1;
else if (head != nullptr) // 1)
{
Node<Data>* temp = head;
while (temp->next != tail) // 2)
temp = temp->next;
delete tail;
tail = temp; // 3)
count--;
return count;
}
}
Please don't do this: if (a == nullptr) {...} else if (a != nullptr) {...} is redundant. Just leave the second if away. It lets a reader believe there could be a third case.
It may be luck that this usually works, but some of the other methods don't properly update the tail pointer, so this might never be true. Validate your pop_front method when there's only one element in the list. Other functions might have similar problems.
Here's the actual problem you're observing. You're not setting the next pointer of the new tail element to null, instead it points to the now deleted tail. Insert tail->next = nullptr after this line.

C++ XOR linked list, deleting data

I have to do XOR linked list. Now im at point that i want to proper way clear memory. I did something like this but it seems doesnt work.
Minimal code i could add to work
void deleteAll(Data* head)
{
if (head == NULL)
cout << "Empty list." << endl;
else
{
if (XOR(head, NULL) == NULL)
{
Data* tmp = NULL;
Data* next;
while (head)
{
next = XOR(head->npx, tmp);
tmp = head;
delete head;
//cout << head->liczba << endl; EDIT <<< this line is not problem
head = next;
}
}
}
}
This is the moment when i alocate data
Data* tmp = new Data;
tmp->liczba = num;
tmp->npx = XOR(*head, NULL);
if (*head != NULL)
{
(*head)->npx = XOR(XOR((*head)->npx,NULL),tmp);
}
*head = tmp;
tmp = NULL;
delete tmp;
In main function after deleting function i run printAll function, then i can see that data has not been cleared.
Edit:
#include <iostream>
using namespace std;
struct Data {
int liczba;
Data* npx;
};
struct Data* XOR(struct Data* prev, struct Data* next)
{
return (Data*)((uintptr_t)(prev) ^ (uintptr_t)(next));
}
void pushEnd(Data** head, int num)
{
Data* tmp = new Data;
tmp->liczba = num;
tmp->npx = XOR(*head, NULL);
if (*head != NULL)
{
(*head)->npx = XOR(XOR((*head)->npx,NULL),tmp);
}
*head = tmp;
tmp = NULL;
delete tmp;
}
void printBackward(Data* head)
{
if (head == NULL)
cout << "Pusta lista." << endl;
else
{
Data* next;
Data* prev = NULL;
while (head)
{
cout << head->liczba << endl;
next = XOR(head->npx, prev);
prev = head;
head = next;
}
}
}
void deleteAll(Data* head)
{
if (head == NULL)
cout << "Empty list." << endl;
else
{
if (XOR(head, NULL) == NULL)
{
Data* tmp = NULL;
Data* next;
while (head)
{
next = XOR(head->npx, tmp);
tmp = head;
delete head;
head = next;
}
}
}
}
int main()
{
Data* head = NULL;
pushEnd(&head, 5);
pushEnd(&head, 10);
pushEnd(&head, 7);
pushEnd(&head, 3);
printBackward(head);
cout << head->liczba;
cout <<endl<< "DEL" << endl;
deleteAll(head);
printBackward(head);
}
In deleteAll you have a line preventing all deletions:
if(XOR(head, NULL) == NULL) { // remove this line
Your deleteAll functions also takes a Data* and all changes you make to head will be local to the function only. A minimal change needed that should make it work is to take head as a Data*& - that is, a reference to a pointer, so that all changes to do to head in your function are actually made to the head you defined in main.
Example:
void deleteAll(Data*& head) {
if(head == nullptr)
cout << "Empty list." << endl;
else {
Data* tmp = nullptr;
Data* next;
while(head) {
next = XOR(head->npx, tmp);
tmp = head;
delete head;
head = next;
}
}
}
You still call it the same way: deleteAll(head);.
If you prefer calling it with deleteAll(&head); you could define the function like this:
void deleteAll(Data** head) {
if(*head == nullptr)
cout << "Empty list." << endl;
else {
Data* tmp = nullptr;
Data* next;
while(*head) {
next = XOR((*head)->npx, tmp);
tmp = *head;
delete *head;
*head = next;
}
}
}

finding min, max, and average of linked list

I have a program in which I'm supposed to build functions using linked lists to perform a variety of tasks. Currently, I am having an issue finding the min and max value of the linked list. For some reason when both come out to be the highest which digit which is 9, and when I try to find the average of the list, it still comes out as 9.
additionally, I think it's interfering with my pop function which is supposed to delete the last item, but when I try to work it by sections one part wont work until he previous section is running for whatever reason.
here is my header
#include <iostream>
using std::cout;
using std::endl;
#ifndef LINKEDLIST_H
#define LINKEDLIST_H
class LinkedList
{
private:
struct Node
{
int data;
Node *next;
};
int size;
Node *head, *tail;
public:
LinkedList();
~LinkedList();
// misc
void display();
// sorting and searching
// reverse --> sorting in descending
int linearSearch(int key);
void sort();
void reverse();
// various math
int min();
int max();
int mean();
// adding
void append(int num);
void insert(int num, int pos);
// removing
void pop();
void remove(int pos);
};
#endif // LINKEDLIST_H
the header's source file
#include "linkedlist.h"
LinkedList::LinkedList()
{
head = nullptr;
tail = nullptr;
size = 0;
}
LinkedList::~LinkedList()
{
if(head != nullptr)
{
Node *temp;
while(head != nullptr)
{
temp = head->next;
// deletes head
delete head;
// goes to next element
head = temp;
}
}
}
void LinkedList::display()
{
Node *temp = head;
for(int i = 0; i < size; i++)
{
cout << temp->data << "\t";
temp = temp->next;
}
cout << endl;
}
void LinkedList::append(int num)
{
// list is empty
if(head == nullptr)
{
head = new Node;
head->data = num;
head->next = nullptr;
// sets tail to head
tail = head;
}
else
{
// creates new node
Node *temp = new Node;
// sets new node data
temp->data = num;
temp->next = nullptr;
// sets previous tail link to new node
tail->next = temp;
// sets this node to new tail
tail = temp;
}
// increments size
size++;
}
void LinkedList::pop()
{
if(size > 1)
{
Node *temp = head;
// loops to node before tail
while(temp->next->next != nullptr)
{
temp = temp->next;
}
// deletes tail
delete tail;
// sets new tail
tail = temp;
tail->next = nullptr;
}
// if there's only one item
else if(size == 1)
{
Node *temp = tail;
// head and tail are now null
head = nullptr;
tail = nullptr;
// deletes node
delete temp;
}
size--;
}
void LinkedList::insert(int num, int pos)
{
if(pos ==0)
{
Node *temp=new Node;
temp->data=num;
temp->next=head;
head=temp;
}
if(pos>1)
{
Node *pre=new Node;
Node *cur=new Node;
Node *temp=new Node;
cur=head;
for(int i=1;i<pos+1;i++)
{
pre=cur;
cur=cur->next;
}
temp->data=num;
pre->next=temp;
temp->next=cur;
}
size++;
}
int LinkedList::linearSearch(int key)
{
Node *temp = head;
for(int i = 0; i < size; i++)
{
if(temp->data == key)
{
return i;
}
temp = temp->next;
}
return -1;
}
int LinkedList::max()
{
int max = INT_MIN;
for(int i = 0; i < size; i++)
{
while (head != NULL)
{
if (head->data < max)
max = head->data;
head = head->next;
}
}
}
int LinkedList::min()
{
int min = INT_MAX;
for(int i = 0; i < size; i++)
{
while (head != NULL)
{
if (head->data < min)
min = head->data;
head = head->next;
}
}
}
void LinkedList::reverse()
{
Node* temp = head;
// Traverse the List
while (temp) {
Node* min = temp;
Node* r = temp->next;
// Traverse the unsorted sublist
while (r)
{
if (min->data < r->data)
min = r;
r = r->next;
}
// Swap Data
int x = temp->data;
temp->data = min->data;
min->data = x;
temp = temp->next;
}
}
void LinkedList::remove(int pos)
{
Node *temp = head;
if(pos ==0)
{
head = temp->next;
free(temp);
}
if(pos>1)
{
for(int i=0; temp!=NULL && i<pos-1;i++)
{
temp=temp->next;
}
temp->next = temp->next->next;
free(temp->next);
temp->next = temp->next;
}
size--;
}
int LinkedList::mean()
{
int sum = 0;
float avg = 0.0;
Node *temp = head;
while (head != NULL)
{
sum += temp->data;
temp = temp->next;
}
// calculate average
avg = (double)sum / size;
}
void LinkedList::sort()
{
Node* temp = head;
// Traverse the List
while (temp) {
Node* min = temp;
Node* r = temp->next;
// Traverse the unsorted sublist
while (r) {
if (min->data > r->data)
min = r;
r = r->next;
}
// Swap Data
int x = temp->data;
temp->data = min->data;
min->data = x;
temp = temp->next;
}
}
And the main
#include <iostream>
#include "linkedlist.h"
using namespace std;
int main()
{
LinkedList nums;
// adding through append
nums.append(8);
nums.append(6);
nums.append(7);
nums.append(8);
nums.append(0);
nums.append(9);
// displays list
cout << "List after append: " << endl;
nums.display();
cout << endl;
// adding through insert
nums.insert(1, 0);
nums.insert(5, 4);
nums.insert(3, 8);
// displays list
cout << "List after inserting: " << endl;
nums.display();
cout << endl;
// testing searching
cout << "Testing linear search:" << endl;
int pres = nums.linearSearch(7);
if(pres < 0)
{
cout << "7 is not present in the list." << endl;
}
else
{
cout << "7 can be found at location " << pres << endl;
}
pres = nums.linearSearch(5);
if(pres < 0)
{
cout << "5 is not present in the list." << endl;
}
else
{
cout << "5 can be found at location " << pres << endl;
}
cout << endl;
// does math
cout << "Minimum, maximum, and average before removing any items: " << endl;
cout << "Min: " << nums.min() << endl;
cout << "Max: " << nums.max() << endl;
cout << "Mean: " << nums.mean() << endl << endl;
// displays items reversed
cout << "Items reversed: " << endl;
nums.reverse();
nums.display();
cout << endl;
// removing through pop
nums.pop();
nums.pop();
// displays list
cout << "List after popping: " << endl;
nums.display();
cout << endl;
// removing through remove
nums.remove(0);
nums.remove(2);
nums.remove(4);
// displays list
cout << "List after removing: " << endl;
nums.display();
cout << endl;
// displays items sorted
cout << "Items sorted: " << endl;
nums.sort();
nums.display();
cout << endl;
// does math
cout << "Minimum, maximum, and average after removing items: " << endl;
cout << "Min: " << nums.min() << endl;
cout << "Max: " << nums.max() << endl;
cout << "Mean: " << nums.mean() << endl << endl;
// testing searching
cout << "Testing linear search:" << endl;
pres = nums.linearSearch(7);
if(pres < 0)
{
cout << "7 is not present in the list." << endl;
}
else
{
cout << "7 can be found at location " << pres << endl;
}
pres = nums.linearSearch(5);
if(pres < 0)
{
cout << "5 is not present in the list." << endl;
}
else
{
cout << "5 can be found at location " << pres << endl;
}
return 0;
}
the only parts I'm really struggling with is the max, min, and mean along with getting my pop function to actually initiate. I know that the pop function is written correctly but ever since I made the max and min it wont work now.
There are several bugs that I have found in the code, and I have several remarks about it:
You should use spaces, and more consistently. There are places without enough spacing, and places with too many blank lines!
If you have two functions such as insert and append or pop and remove, they should use each other, meaning, append is just insert(0) (notice how I changed it in the code).
You are using double loops where it doesn't make sense (it isn't an error, but it is a bug!).
In the function max, you were doing the wrong comparison, asking if max is bigger than the current value...
You never return a value from min and max, which should at least create a warning in the compilation process!
You were creating empty nodes, and then you just put different values in their pointers, meaning that this new memory was still allocated (since there was no delete), but there was no way to access these anymore (this is a memory leak).
The biggest bug of all - When you loop in the min and max functions, you change the head of the list, which is a major bug (and that is why you got bugs after using this function). The solution is a simple but important lesson in C++ - Const Correctness.
What is const correctness, and why is it important?
When you have a function, that does not change the state of your object, it should be declared const. This is our way to tell the compiler (and other programmers) that it mustn't change the state of our object. For example, min, max and average are classic const functions - they simply make a calculation that does not change the list, and return. If you had written const in the declaration of those, the compilation would have failed, since you actually changed the list (changing the head), although you shouldn't!
Moreover, when receiving objects into a function, whenever possible, you should make the const T& where T is a type. They will enforce that you are using only const functions of this type.
Also, I suggest compiling (at least on g++) with the flags -Wpedantic -Werror'. The first adds some warnings about ISO C++ standards and the second makes all warnings into errors (and thus, yourmin,maxandmean` should not compile, since they don't return a value).
Here is the code:
class LinkedList
{
private:
struct Node
{
int data;
Node *next;
Node(int data_, Node* next_ = nullptr) :
data(data_),
next(next_)
{
}
};
int size;
Node *head, *tail;
public:
LinkedList();
~LinkedList();
void clear();
// various math
int min() const;
int max() const;
int average() const;
// adding
void append(int data);
void insert(int data, int pos);
// removing
void pop();
void remove(int pos);
};
LinkedList::LinkedList()
{
head = nullptr;
tail = nullptr;
size = 0;
}
LinkedList::~LinkedList()
{
clear();
}
void LinkedList::clear()
{
if (head != nullptr)
{
Node *temp;
while(head != nullptr)
{
temp = head->next;
delete head;
head = temp;
}
}
head = nullptr;
tail = nullptr;
size = 0;
}
void LinkedList::display()
{
Node *temp = head;
for(int i = 0; i < size; i++)
{
std::cout << temp->data << "\t";
temp = temp->next;
}
std::cout << std::endl;
}
void LinkedList::insert(int data, int pos)
{
if (pos == 0)
{
Node* prev_head = head;
head = new Node(data, prev_head);
if (size == 0)
{
tail = head;
}
}
else
{
Node *pre=nullptr;
Node *cur = head;
for(int i = 0 ; i < pos + 1; ++i)
{
pre = cur;
cur = cur->next;
}
Node *temp = new Node(data, cur);
pre->next = temp;
}
++size;
}
void LinkedList::append(int data)
{
insert(data, 0);
}
void LinkedList::pop()
{
if (size == 1)
{
Node *temp = tail;
head = nullptr;
tail = nullptr;
delete temp;
}
else
{
Node *temp = head;
while(temp->next != tail)
{
temp = temp->next;
}
Node* node_to_pop = tail;
tail = temp;
tail->next = nullptr;
delete node_to_pop;
}
--size;
}
int LinkedList::max() const
{
int max = INT_MIN;
for (Node* temp = head; temp != nullptr; temp = temp->next)
{
if (temp->data > max)
{
max = temp->data;
}
}
return max;
}
int LinkedList::min() const
{
int min = INT_MAX;
for(Node* temp = head; temp != nullptr; temp = temp->next)
{
if (head->data < min)
{
min = temp->data;
}
}
return min;
}
int LinkedList::average() const
{
int sum = 0;
for(Node* temp = head; temp != nullptr; temp = temp->next)
{
sum += temp->data;
temp = temp->next;
}
return (double)sum / size;
}

UpdateByValue Function is not doing anything?

#include <iostream>
#include <string>
using namespace std;
class Person{
public:
string name;
int age, height, weight;
Person(string name = "empty", int age = 0, int height = 0, int weight = 0) {
this->name = name;
this->age = age;
this->height = height;
this->weight = weight;
}
Person operator = (const Person &P) {
name = P.name;
age = P.age;
height = P.height;
weight = P.weight;
return *this;
}
void setAge(int a){
age = a;
}
int getAge(){
return age;
}
friend ostream& operator<<(ostream& os, const Person& p);
};
ostream& operator<<(ostream& os, Person& p) {
os << "Name: " << p.name << " " << "Age: " << p.age << " " << "Height: " << p.height << " " << "Weight: " << p.weight << "\n";
return os;
};
class Node {
public:
Person* data;
Node* next;
Node(Person*A) {
data = A;
next = nullptr;
}
};
class LinkedList {
public:
Node * head;
LinkedList() {
head = nullptr;
}
void InsertAtHead(Person*A) {
Node* node = new Node(A);
node->next = head;
head = node;
}
void InsertAtEnd(Person*A) {
if (head == nullptr) {
InsertAtHead(A);
}
else {
Node* node = new Node(A);
Node* temp = head;
while (temp->next != nullptr) {
temp = temp->next;
}
temp->next = node;
}
}
void InsertAtPosition(Person*A, int pos) {
if (head == nullptr) {
InsertAtHead(A);
}
else {
Node* node = new Node(A);
Node* temp = head;
for (int i = 1; i < pos - 1; i++) { temp = temp->next; }
node->next = temp->next;
temp->next = node;
}
}
void DeleteByValue(string search_name) {
Node* temp = head;
Node* prev = nullptr;
while (temp != nullptr) {
if (temp->data->name == search_name) {
if (prev != nullptr) {
prev->next = temp->next;
}
else {
head = temp->next;
}
delete temp;
temp = nullptr;
}
else {
prev = temp;
temp = temp->next;
}
}
}
void DeleteFromHead() {
if (head != nullptr) {
Node* temp = head;
head = head->next;
delete temp;
}
}
void DeleteFromEnd() {
Node* prev = nullptr;
Node* temp = head;
if (head == nullptr) { cout << "Nothing to delete" << endl; }
else if (head->next == nullptr) { DeleteFromHead(); }
else {
while (temp->next != nullptr) {
prev = temp;
temp = temp->next;
}
prev->next = nullptr;
delete temp;
}
}
void DeleteAtPosition(int pos) {
Node* prev = nullptr;
Node* temp = head;
if (head == nullptr) { cout << "Nothing to delete" << endl; }
else if (pos == 1) { DeleteFromHead(); }
else {
for (int i = 1; i < pos; i++) {
prev = temp;
temp = temp->next;
}
prev->next = temp->next;
delete temp;
}
}
void UpdateAtPosition(Person*A, int pos) {
if (head == nullptr) { cout << "No element in the list"; return; }
if (pos == 1) { head->data = A; }
else {
Node* temp = head;
for (int i = 1; i < pos; i++) {
temp = temp->next;
}
temp->data = A;
}
}
void UpdateByValue(string name, int newAge) {
Node* temp = head;
Person* p = new Person();
while(temp != nullptr){
if(temp->data->name == name){
p->setAge(newAge);
}else{
temp = temp->next;
}
}
}
void Print() {
Node* temp = head;
while (temp != nullptr) {
cout << *(temp->data);
temp = temp->next;
}
cout << endl;
}
};
int main() {
LinkedList* list = new LinkedList();
list->InsertAtHead(new Person("Samantha", 20, 63, 115)); list->Print();
list->InsertAtEnd(new Person("Chris", 19, 70, 200)); list->Print();
list->DeleteByValue("Chris"); list->Print();
list->UpdateByValue("Samantha", 21); list->Print();
return 0;
}
I am new to C++ so excuse any poorly written code, but I am trying to use the function UpdateByValue to update the age of Samantha. It may look very wrong right now, but I have tried 20 different things and cannot figure out what I am doing wrong. I used to go to school at a community college where I learned Java so Im catching up to everyone in C++. A lot of it is similar but I struggle with little things like this. Could anyone explain to me how to fix the UpdateByValue function so that it will change the age of my Person object of choice? I want to be able to type the name as the first parameter and change the age of that person with the second parameter. If something is unclear and needs more explaining please let me know, I just need help. Thanks in advance, and please feel free to give any other constructive criticism. I am trying to get as good as I can.
Let's take a walk through UpdateByValue. I'll comment as we go.
void UpdateByValue(string name, int newAge) {
Node* temp = head;
Person* p = new Person();
while(temp != nullptr){ // keep looking until end of list
if(temp->data->name == name){ // found node with name
p->setAge(newAge); // update a different node
// never advance node so we can't exit function
}else{
temp = temp->next;
}
}
}
Try instead
void UpdateByValue(string name, int newAge) {
Node* temp = head;
// Person * p is not needed
while(temp != nullptr){ // keep looking until end of list
if(temp->data->name == name){ // found node with name
temp->data->setAge(newAge); // update the found node
return; // done searching. Exit function
}else{
temp = temp->next;
}
}
}

Segmentation Fault (core dumped) when trying to run Queue program - C++

I keep getting a Segmentation fault (core dumped) error every time I try to run my code with g++ on Linux. It compiles fine, but then that happens ... All the functions (remove, add and print) seem to have the same problem, I can't seem to figure out what's wrong... Please heeeelppp.
#include <iostream>
#include <string>
using namespace std;
//Create a node struct
struct Node {
int data;
Node *next;
Node *prev;
};
class Queue {
private:
Node *head;
Node *tail;
int size;
public:
Queue();
~Queue();
void add(int d);
int remove();
bool isEmpty();
void printQueue(bool o);
};
//set to NULL
Queue::Queue() {
head = tail = NULL;
size = 0;
}
//destructor
//call remove until empty
Queue::~Queue() {
while (!isEmpty())
remove();
}
//adds a node with the given data at the back of the queue
void Queue::add(int d) {
Node *temp = new Node();
temp->data = d;
temp->next = NULL;
if (isEmpty()) {
//add to head
head = temp;
} else {
//append
tail->next = temp;
tail = temp;
cout << "Added: " << tail->data << endl;
}
size++;
}
//removes the node at the head of the queue and returns its data
int Queue::remove() {
if (isEmpty()) {
cout << "The queue is empty." << endl;
} else {
Node *temp = new Node;
temp = head;
int value = head->data;
//moves pointer to next node
head = head->next;
cout << "Removed: " << head->data << endl;
size--;
delete temp;
return value;
}
}
//determines if the queue is empty
bool Queue::isEmpty() {
return (size == 0);
}
//prints the contents of the queue from front to back, or front
//to back, depending on the value of the parameter
void Queue::printQueue(bool o) {
if (isEmpty()) {
cout << "The queue is empty." << endl;
} else {
Node *p = new Node;
if (o == true) {
cout << "Printing in front to back:" << endl;
//print front to back
while(p != NULL) {
p = head;
cout << p->data << " ";
p = p->next;
}
} else if (o == false) {
cout << "Printing in back to front:" << endl;
//print back to front
while (p != NULL) {
p = tail;
cout << p->data << " ";
p = p->prev;
}
}
}
}
int main() {
Queue q;
q.add(8);
return 0;
}
EDIT: I've made some changes to the code... But I'm still getting the same error. I assume I'm not updating the head and the tail and/or the next and prev nodes correctly... I don't know why it's wrong or what I'm missing, though.
#include <iostream>
#include <string>
using namespace std;
struct Node {
int data;
Node *next;
Node *prev;
};
class Queue {
private:
Node *head;
Node *tail;
int size;
public:
Queue();
~Queue();
void add(int d);
int remove();
bool isEmpty();
void printQueue(bool o);
};
Queue::Queue() {
head = tail = NULL;
size = 0;
}
Queue::~Queue() {
while (!isEmpty())
remove();
}
void Queue::add(int d) {
Node *temp = new Node;
temp->data = d;
temp->next = NULL;
temp->prev = tail;
if (isEmpty()) {
//add to head
head = temp;
} else {
//append
tail->next = temp;
tail = temp;
cout << "Added: " << tail->data << endl;
}
size++;
}
int Queue::remove() {
if (isEmpty()) {
cout << "The queue is empty." << endl;
return 0;
} else {
Node *temp = head;
int value = head->data;
cout << "Removed: " << head->data << endl;
//moves pointer to next node
head = head->next;
head->prev = NULL;
size--;
delete temp;
return value;
}
}
bool Queue::isEmpty() {
return (size == 0);
}
void Queue::printQueue(bool o) {
if (isEmpty()) {
cout << "The queue is empty." << endl;
} else {
Node *p;
if (o == true) {
p = head;
cout << "Printing in front to back:" << endl;
//print front to back
while(p != NULL) {
cout << p->data << " ";
p = p->next;
}
} else if (o == false) {
p = tail;
cout << "Printing in back to front:" << endl;
//print back to front
while (p != NULL) {
cout << p->data << " ";
p = p->prev;
}
}
}
}
int main() {
Queue q;
q.add(9);
q.add(10);
q.add(11);
q.add(12);
q.add(13);
q.add(14);
q.add(15);
q.add(16);
q.remove();
q.remove();
q.printQueue(true);
q.printQueue(false);
return 0;
}
Lots of problems:
You have a double-linked Node but never update its prev member in the add/remove methods.
You are keeping track of both the Queue head/tail but don't properly update them when you add/remove nodes.
Both your forward and reverse loops in printQueue() are wrong and result in an infinite loop for any queue with 2 or more elements. Queue output should be just something like:
Node *p = head;
while (p != NULL)
{
cout << p->data << " ";
p = p->next;
}
Possible null pointer deference in remove() at cout << "Removed: " << head->data << endl; since you've already moved the head pointer by this time. Move the head after the cout.
Memory leak in Queue::remove() at Node *temp = new Node;. Just do Node* temp = head;.
Memory leak in Queue::printQueue() at Node *p = new Node;. You don't need to allocate a node here.
No return value in remove() for an empty queue.
Edit
Don't forget to initialize the tail when adding a node to an empty list:
if (isEmpty()) {
head = temp;
tail = temp;
}
To remove a node from the head of a non-empty list it should be something like:
Node *temp = head;
head = head->next;
if (head) head->prev = NULL;
size--;
delete temp;
if (isEmpty()) tail = NULL;