How to delete element from list in c++ - c++

I am currently making a singly linked list in C++
Now I'm trying to make a function showList that prints the content of the list and if it is empty, prints "Empty list". However, right now it prints the list and "Empty list" every single time. When the list is empty, it prints an empty line and in new line "Empty list"
Here is my current code:
template <typename T>
struct Node {
T data;
Node* next;
};
template <typename T>
void showList(const Node<T>* head){
while (head != nullptr){
std::cout << head->data << " " ;
head = head->next;
}
std::cout << std::endl;
if(head->data = 0){
std::cout << "Empty list"<< std::endl;
}
}

Assuming you mean an empty list is a list where head is nullptr, you could check it explicitly:
void showList(const Node<T>* head) {
if (head == nullptr) {
std::cout << "Empty list"<< std::endl;
return;
}
while (head != nullptr){
std::cout << head->data << " " ;
head = head->next;
}
std::cout << std::endl;
}

Related

Displaying Reversed Linked List

I am trying to reverse a liked list in c++ but unfortunately I am unable to do that. Here is the entire program I am working on. I don't know where the problem is. The problem I think is either
reverse()
or
displayList()
void reverse()
{
struct node *curr = head;
struct node *next = NULL;
struct node *prev = NULL;
while (curr != NULL)
{
next = curr->next;
curr->next = prev;
prev = curr;
curr = next;
}
head = prev;
}
void displayList()
{
while (head != NULL)
{
cout << head->data << " ";
head = head->next;
}
cout << endl;
}
int main(){
createNode(100);
createNode(310);
createNode(150);
createNode(300);
createNode(500);
cout << "Original List" << endl;
displayList();
cout << endl << "Reversed List" << endl;
reverse();
displayList();
return 0;
}
When I comment displayList() when I first called it, it worked. Basically the function runs only one time.
Assuming displayList to be a member function of some List type because there is no local variable head anywhere: You destroy your list (leaking all data) when iterating over it in displayList. Here are some fixes.
void displayList() const
{
node* curr = head;
while (curr != nullptr)
{
std::cout << curr->data << ' ';
curr = curr->next;
}
std::cout << '\n';
}
If you get into the habit of making functions const that are not supposed to change the object, your compiler would have spotted this for you.

read access violation, temp was 0xDDDDDDDD

void deleteBasedOnID(student* head,student* tail,int stu_ID)
{
if (head == NULL)
{
std::cout << "nothing to be deleted";
}
else if (stu_ID == head->stu_ID)
{
//delete from the beginning
temp = head->next;
if (temp == NULL)
{
tail = NULL;
}
else
{
temp->prev = NULL;
}
std::cout << "Deleted ID: " << head->stu_ID << std::endl;
delete head;
head = temp;
}
else
{
//start from second
temp = head;
previous = NULL;
while (stu_ID != temp->stu_ID)
{
previous = temp;
temp = temp->next;
if (temp == NULL)
{
std::cout << "no such ID!" << std::endl;
return;
}
}
previous->next = temp->next;
if (temp->next == NULL)
{
tail = previous;
}
else
{
temp->next->prev = previous;
}
std::cout << "Deleted ID: " << temp->stu_ID << std::endl;
delete temp;
}
}
I have a student struct and global pointers head and tail, I put the said head and tail into deleteBasedOnID head and tail arguments
it works fine for if(head == NULL) or the else block but however whenever I try to delete from the beginning, it works fine internally but after I tried to display the list, error occurred.
This is my display function body
void display()
{
temp = head;
while (temp != NULL)
{
std::cout << "Student ID: " << temp->stu_ID << std::endl;
temp = temp->next;
}
}
main function
int main()
{
head = NULL;
tail = NULL;
temp = NULL;
int id;
std::cout << std::endl;
std::cout << "Enter the id you want to delete: ";
std::cin >> id;
deleteBasedOnID(head, tail, id);
std::cout << "New sorted list" << std::endl;
display();
return 0;
}
In your deleteBasedOnId-function, you change the value for the parameter head, which is a copy of the pointer to head you made in main. The original pointer in main keeps its value, which now points to deleted memory, hence the segfault. You can take a reference to the pointer to head as parameter to solve this problem:
void deleteBasedOnID(student*& head,student*& tail,int stu_ID)

Print a linkedlist

Given the name of a node, this function should search the linked list; if its found inside, then return a pointer that points to that node, otherwise return null. Note: I am certain I have written this function successfully.
// getNode
Node *LinkedList::getNode(string name)
{
Node *temp = head;
while (temp != NULL)
{
if (temp->name.compare(name) == 0)
return temp;
temp = temp->next;
}
return NULL;
}
Given a node, this function prints: teamName(winScore-loseScore) on screen. Examples: UCLA(25-13) or Texas A&M(31-25). Note: I am sure I have written this function successfully.
// printNode
void LinkedList::printNode(Node *node)
{
if (node == NULL)
return;
else {
cout << node->name << "(" << node->winScore;
cout << "-" << node->loseScore << ")";
}
}
Given a team name, this function is supposed to print all the nodes in its adjacency list one-by-one in the following format (NOTE: the following is just one example!) This is where I think I am wrong.
Missouri University beat: New Mexico(52-23), Salisbury (48-31), Virginia (34-9)
void LinkedList::printList(string name)
{
if (head == NULL)
cout << "\n Empty list" << endl;
else {
Node *temp = head;
while (temp != NULL)
{
cout << temp->name << " beat: " << temp->name << endl; // Is this right?
temp = temp->next;
}
}
}
I'm guessing that this is close to what you want:
void LinkedList::printList(string name)
{
// find the node for the name you supply
// (or else I don't understand why 'name' is supplied to this function)
Node *temp = getNode(name);
if (temp) { // node with name found
if (temp->next) { // there's at least one adjacent node
cout << temp->name << " beat: ";
while ((temp = temp->next) != nullptr) {
printNode(temp);
if (temp->next) cout << ", ";
};
cout << "\n";
} else { // no adjacent nodes
cout << temp->name << " did not beat anyone\n";
}
}
}

Templated Linked List giving wrong output when asked to print a node

I'm creating a database for school records for a project. I have a Student, Faculty, and Administrator class that all inherit things from a Person class. When I add the different objects to a Node, the information is stored in that Node (I see it via the debugger), however when I go to print a Node, I get
00266A88
instead of
Full Name: Reed
M Number: 999
Email:
and so on.
I'm just not sure what is causing the problem. Here is my method to print a node from the list:
template <typename T>
void TemplatedList<T>::printSpecific(int m_Number)
{
Node * Current = Head;
//If there is nothing in the list but the dummy head node, then return because there's nothing to print
if(Head->next == NULL)
{
cout << "Cannot print (M" << m_Number << "), NOT found!" << endl;
return;
}
else
Current = Current->next;
// While Current->next isn't equal to NULL, go through the list and see if the M-Numbers match. If they do, print the student and return
while(Current->next != NULL)
{
if(m_Number == Current->data->getM_Number())
{
cout << Current->data;
return;
}
else
{
Current = Current->next;
}
}
if(Current->next == NULL)
{
if(m_Number == Current->data->getM_Number())
{
cout << Current->data;
return;
}
else
{
cout << "Cannot print (M" <<m_Number << "), NOT found!" << endl;
return;
}
}
}
Here is the function to add one of the of the objects to the list:
template<typename T>
void TemplatedList<T>::addTemplatedList(T newAddition)
{
//Points to current node we're using
Node* Current = Head;
//Points to the node previous in the list to the current
Node* Previous = Head;
//Creates a new Node
Node* newNode = new Node;
//Assigns new Student information to new Node
newNode->data = newAddition;
// Check to see if the Head is only thing in the list. If it is, just place the new Node directly after the Head
if (Head->next == NULL)
{
Head->next = newNode;
newNode->next = NULL;
return;
}
else
{
while (Current->next != NULL)
{
if (newAddition->getM_Number() < Current->next->data->getM_Number())
{
newNode->next = Current->next;
Previous->next = newNode;
return;
}
else if (newAddition->getM_Number() == Current->next->data->getM_Number())
{
cout << "Person with M Number " << newAddition->getM_Number() << " not added because they are already in database." << endl;
delete newNode;
return;
}
Current = Current->next;
Previous = Previous->next;
}
if (Current->next == NULL)
{
Current->next = newNode;
newNode->next = NULL;
}
}
}
And finally here is how I'm calling the add function and creating a new object:
if (inputArray[0] == "A")
{
cout << "Adding Administrator: " << endl <<"\tFull Name:\t" << inputArray[1] << endl;
cout << "\tM Number:\t" << inputArray[2] << endl << "\tEmail Addr:\t" << inputArray[3] << endl << "\tTitle:\t " << inputArray[4] << endl;
Administrator *newAdmin = new Administrator;
istringstream stream (inputArray[2]);
int number;
stream >> number;
newAdmin->setAdmin(inputArray, number);
templatedList.addTemplatedList(newAdmin);
}
I would really appreciate and help that I can get because I'm just not sure what's happening or why it's giving me that incorrect output.
It looks like Node::data is a pointer to Administrator in this example. So when you do
cout << Current->data;
it merely outputs the pointer value. Assuming that you have implemented operator<< for the Administrator class, all you need to do is dereference:
cout << *Current->data;

generic linked list pointer access

I am writing a generic linked list in C++ using templates, and am experiencing Segmentation Faults when accessing Node values.
To make the test case simpler, I have implemented a fixed size, two node, linked list.
I have two questions:
1a) Why isn't aList.headNodePtr->prevNodePtr set to NULL?
1b) Why isn't aList.tailNodePtr->nextNodePtr set to NULL?
I set both of these values to NULL in the LinkedList constructor, but the output in main shows that:
head prevAddress: 0x89485ed18949ed31
tail nextAddress: 0x7fffe8849679
2) Why does the following line in main() cause a Seg Fault?
aList.headNodePtr->nodeValue = 1;
The full code is below:
#include <iostream>
using namespace std;
template <class T>
class Node {
public:
Node<T>* prevNodePtr;
Node<T>* nextNodePtr;
T nodeValue;
};
template <typename T>
class LinkedList {
public:
Node<T>* headNodePtr;
Node<T>* tailNodePtr;
LinkedList() {
Node<T>* headNodePtr = new Node<T>;
Node<T>* tailNodePtr = new Node<T>;
headNodePtr->prevNodePtr = NULL;
headNodePtr->nextNodePtr = tailNodePtr;
tailNodePtr->prevNodePtr = headNodePtr;
tailNodePtr->nextNodePtr = NULL;
}
~LinkedList() {
headNodePtr = NULL;
tailNodePtr = NULL;
delete headNodePtr;
delete tailNodePtr;
}
};
int main()
{
LinkedList<int> aList;
cout << "head Value: " << aList.headNodePtr->nodeValue << endl;
cout << "head prevAddress: " << aList.headNodePtr->prevNodePtr << endl;
cout << "head nextAddress: " << aList.headNodePtr->nextNodePtr << endl;
cout << "tail Value: " << aList.tailNodePtr->nodeValue << endl;
cout << "tail prevAddress: " << aList.tailNodePtr->prevNodePtr << endl;
cout << "tail nextAddress: " << aList.tailNodePtr->nextNodePtr << endl;
aList.headNodePtr->nodeValue = 1;
}
You're not actually setting the members, you're setting the locals you declared in the ctor:
Node<T>* headNodePtr; // <-- MEMBERS
Node<T>* tailNodePtr;
LinkedList() {
Node<T>* headNodePtr = new Node<T>; // <-- LOCALS
Node<T>* tailNodePtr = new Node<T>;
Try this instead:
Node<T>* headNodePtr; // <-- MEMBERS
Node<T>* tailNodePtr;
LinkedList() {
headNodePtr = new Node<T>; // <-- MEMBER ACCESS
tailNodePtr = new Node<T>;