I have this linked list adt. The only problem i am having is in this remove function. I tried dry running it but can't figure it out correctly. Please someone explain it
void list::remove(int v)
{
node *temp, *pre;
temp = head;
if(temp->data==v)
{
head = temp->next;
delete temp;
cout << endl << v << "has been deleted" <<endl;
return;
}
pre = temp;
while(temp!=0)
{
if(temp->data==v)
{
pre->next = temp->next;
delete temp;
cout << "\nValue deleted" <<endl;
return;
}
pre = temp;
temp = temp->next;
}
cout << endl << v << "not found" <<endl;
}
int main()
{
list l;
l.insert(8);
l.insert(9);
l.insert(10);
l.display();
cout << "After deleting" <<endl;
l.remove(9);
l.display();
}
The code appears to be correct upon first glance. A quick explanation of it would be:You are making two node pointers, one to point to the current element on the list and one to point to the previous one. First case would be that the element you are trying to delete is in the beginning of the list(so it is the head).In this case you move head to the next element(head=temp->next) and delete the node. The other case would be that the element is somewhere in the list. Using the while loop you scan through the list (pre=temp, temp=temp->next are to move you to the next elements) and using the if condition you check if the element is the one you are looking for.
Related
I've read the questions and not seen answer to mine.
Most people use structs for these and after testing reference code I see the struct version is functional but, why is class version not?
#include <iostream>
using namespace std;
// I'm still bad at pointer logic but it makes sense.
// REFERENCES
// https://www.geeksforgeeks.org/queue-linked-list-implementation/
// stack linked list assignment earlier in semester
// https://stackoverflow.com/questions/29787026/c-queue-from-linked-list
class Node {
public:
int data;
Node *next; // controls flow of nodes
};
class Queue {
public:
Queue();
~Queue();
void enQueue(int data);
void deQueue();
bool isEmpty();
//private: all set to public because I don't want to make a print function
Node *front;
Node *rear;
int counter;
};
Queue::Queue()
{
front = NULL;
rear = NULL;
}
Queue::~Queue() {
if (rear == NULL && front == NULL)
{
cout << "Nothing to clean up!" << endl;
}
else
{
cout << "Delete should be happening now...";
}
}
void Queue::enQueue(int data) {
// create new node of queue structure
Node *temp = new Node;
temp->data = data;
// write like this line below if not temp->data = data;
// Node *temp = new Node(data);
// if the queue is empty, first node.
if (rear == NULL)
{
front = temp;
rear = temp;
return;
}
// assign data of queue structure
rear->next = temp; // point rear pointer to next pointer = assign to temp
rear = temp; // assign rear to temp keep front pointer at beginning fifo
}
void Queue::deQueue()
{
// if queue is empty, return NULL
if (front == NULL)
{
cout << "Queue is empty, sorry!";
return;
}
Node* temp = front; // assign front
//problem here
front = front->next; // move front one node ahead
if(front == NULL)
{
rear = NULL;
}
delete (temp);
return;
}
bool Queue::isEmpty()
{
// cout << "functions";
// cout << endl;
return (front == NULL && rear == NULL);
}
int main()
{
Queue yay;
yay.isEmpty();
yay.deQueue();
cout << endl;
yay.enQueue(5);
yay.enQueue(6);
cout << "Queue Front : " << (yay.front)->data << endl;
yay.deQueue();
cout << "After deqQueue " << endl;
cout << "Queue Front : " << (yay.front)->data << endl;
yay.deQueue();
cout << "Queue Front : " << (yay.front)->data << endl;
yay.deQueue(); // <- Problem here
yay.deQueue();
cout << "completed" << endl;
}
I've isolated the problem to line 90
//problem here
front = front->next; // move front one node ahead
it causes this code in int main() to not print
yay.deQueue(); // <- Problem here
yay.deQueue();
cout << "completed" << endl;
I know I am weak at pointer directing and so forth, so if could please tell me what I am not seeing would be appreciated, I've been poking at it for a while now and did not resolve.
This link for code through online gdb
https://onlinegdb.com/0B0KzcHMa
This is the output with line
Queue is empty, sorry!
Queue Front : 5
After deQueue
Queue Front : 6
And the output with line 90 and 96 commented out //96 commented to avoid double free
Queue is empty, sorry!
Queue Front : 5
After deQueue
Queue Front : 5
Queue Front : 5
completed
Delete should be happening now...
Now I know, I know I should be better at this traversal of nodes business
but, I am not seeing it and this may help me remember it in the future :X
I believe its a simple fix but, everything I try reaches the former output
rather than the later with intended data represented, I believe it is
nexting out into random memory making memory leak or memory pointing wherever
thus it never goes back to main to complete terminal messages
The problem is here:
Queue yay;
yay.isEmpty();
yay.deQueue();
cout << endl;
yay.enQueue(5);
yay.enQueue(6);
cout << "Queue Front : " << (yay.front)->data << endl;
yay.deQueue();
cout << "After deqQueue " << endl;
cout << "Queue Front : " << (yay.front)->data << endl;
yay.deQueue();
cout << "Queue Front : " << (yay.front)->data << endl; // <<==== HERE
The queue had two elements, 5 and 6, inserted. Then one was popped, then the other. That means yay.front is now nullptr per your deQueue logic reading the end of the list. Therefore, reading (yay.front)->data invoke undefined behavior by dereferencing an invalid pointer (in this case a pointer containing nullptr).
Lose that dereference (one way or another) and the code shouldn't fault any longer.
I am trying to make a mask delivery, ordering service code.
The function order will add a new order to order list.
The function output will output the list from newest to oldest order.
The function deliver removes the oldest order.
The following is the code:
#include <iostream>
#include <string>
using namespace std;
struct Mask {
string type;
string customer;
Mask *next;
};
void order(Mask *&head, string type, string customer){
cout << "Ordering " << type << " for " << customer << endl;
Mask *oldHead = head;
head = new Mask;
head->type = type;
head->customer = customer;
head->next = oldHead;
}
void output(Mask *head){
cout << "Outputting order list " << endl;
for (Mask *p = head; p != NULL; p = p->next)
cout << " " << p->type << " for " << p->customer << endl;
}
void deliver(Mask *&head){
if (head->next == NULL){
cout << "Delivering " << head->type;
cout << " for " << head->customer << endl;
delete head;
}
else
deliver(head->next);
}
int main()
{
Mask *head = NULL;
order(head, "3M-N95", "Alice");
order(head, "OxyAir", "Burce");
order(head, "3M-N95", "Cindy");
output(head);
deliver(head);
output(head);
}
Everything runs smoothly, but it says segmentation error(core dumped) at the end. I tried adding this:
if (head->next->next == NULL){
deliver(head->next);
head->next == NULL;
}
But the problem still exists. Any help is appreciated.
I changed deliver to this:
void deliver(Mask *&head){
if (head->next->next == NULL){
cout << "Delivering " << head->next->type;
cout << " for " << head->next->customer << endl;
head->next = head->next->next;
delete head->next;
}
else
deliver(head->next);
}
Apparently, just setting the pointer to NULL does not fix the problem, so I just updated it so that the second last pointer pointed directly to the end.
in "deliver" you force the function to meet the condition if(head->next == NULL)
and then trying to reach head->next->next which is like trying to say null->next (resulting with segmentation fault).
I would recommend traversing to the last "Mask" object with a while loop instead of using all those "if" statements which lead to the same result, or at least change the second if to else if in order to avoid meeting this "if" again.
First of all, apologies if this is a duplicate question. I'm just learning C++ and probably don't know the correct search terms to find what I'm sure has already been asked.
Anyways, I'm teaching myself C++ by working through the 30 days of code on HackerRank. However, I've hit a roadblock that I can't seem to solve when asked to implement an insert method for a LinkedList. Conceptually, I know what needs to be done, but syntactically I'm running into an issue.
Below is my code, with debugging printouts included. What seems to be happening is that new_node keeps getting put in the same location in memory, regardless of which loop iteration its on. How do I ensure this gets a new place in memory? I seem to get the same behavior regardless of if I declare new_node as static or not.
Here's the code:
#include <iostream>
#include <cstddef>
using namespace std;
class Node
{
public:
int data;
Node *next;
Node(int d){
data=d;
next=NULL;
}
};
class Solution{
public:
/// ----- MY CODE BEGINS HERE:
Node* insert(Node *head,int data)
{
cout << "----------" << endl;
cout << data << endl;
int i = 0;
if (head){
Node *curr = head;
Node *next = curr->next;
while(next){
cout << data << "," << i << ": " << curr << "," << curr->next
<< "," << curr->data << endl;
i++;
curr = curr->next;
next = curr->next;
}
cout << data << "," << i << ": " << curr << "," << curr->next
<< "," << curr->data << endl;
static Node new_node = Node(data);
curr->next = &new_node;
cout << " *** Adding " << data << " at " << curr->next
<< " and next points to: " << (curr->next)->next << endl;
return head;
}
else{
static Node new_head = Node(data);
cout << " *** Adding " << data << " at " << &new_head
<< " and next points to: " << new_head.next << endl;
return &new_head;
}
}
// ------- MY CODE ENDS HERE
void display(Node *head)
{
Node *start=head;
while(start)
{
cout<<start->data<<" ";
start=start->next;
}
}
};
int main()
{
Node* head=NULL;
Solution mylist;
int T,data;
cin>>T;
while(T-->0){
cin>>data;
head=mylist.insert(head,data);
}
mylist.display(head);
}
When I run this with the sample input of (4, 2, 3, 4, 1), I get the following:
----------
2
*** Adding 2 at 0x6022e0 and next points to: 0
----------
3
3,0: 0x6022e0,0,2
*** Adding 3 at 0x7fff3ddc1d80 and next points to: 0
----------
4
4,0: 0x6022e0,0x7fff3ddc1d80,2
4,1: 0x7fff3ddc1d80,0,3
*** Adding 4 at 0x7fff3ddc1d80 and next points to: 0x7fff3ddc1d80
----------
1
1,0: 0x6022e0,0x7fff3ddc1d80,2
1,1: 0x7fff3ddc1d80,0x7fff3ddc1d80,4
1,2: 0x7fff3ddc1d80,0x7fff3ddc1d80,4
1,3: 0x7fff3ddc1d80,0x7fff3ddc1d80,4
1,4: 0x7fff3ddc1d80,0x7fff3ddc1d80,4
1,5: 0x7fff3ddc1d80,0x7fff3ddc1d80,4
and this continues until a Segmentation Fault ebcause its caught in an infinite loop...
Any ideas why new_node keeps getting placed in the same memory location (with or without the static)? Is this not even the main issue and I'm completely missing the point? Thanks in advance!
-- C++ neophyte.
EDIT: The suggested duplicate doesn't quite address the question here. My trouble was not understanding the difference between pointers and references, but rather the difference between:
Node node_1 = Node(data);
static node_2 = Node(data);
node_3 = new Node(data);
As I was unaware of the new operator at the time of writing the question (obviously!), I did not know to (a) search for this or (b) include this term in the title. The title has been edited for clarity, and this edit has been included for future readers.
When you declare a variable static, there's only one copy of that variable. It gets created the first time you execute the declaration, and future calls to the function reuse the same data. So every time you use new_node, it's the same node.
You need to allocate dynamic data with the new operator. As the operator name implies, this creates a new object every time you use it. When you add a remove() operation to the class, it will use delete to free the memory.
Node* insert(Node *head,int data)
{
cout << "----------" << endl;
cout << data << endl;
int i = 0;
if (head){
Node *curr = head;
Node *next = curr->next;
while(next){
cout << data << "," << i << ": " << curr << "," << curr->next
<< "," << curr->data << endl;
i++;
curr = curr->next;
next = curr->next;
}
cout << data << "," << i << ": " << curr << "," << curr->next
<< "," << curr->data << endl;
Node *new_node = new Node(data);
curr->next = new_node;
cout << " *** Adding " << data << " at " << curr->next
<< " and next points to: " << (curr->next)->next << endl;
return head;
}
else{
Node *new_head = new Node(data);
cout << " *** Adding " << data << " at " << &new_head
<< " and next points to: " << new_head->next << endl;
return new_head;
}
}
you use a static variables. These are created only once, and are the same for every function call!
your intend is to create a new Node always, so these variables are not static!
try it out with
Node* new_head = new Node(data);
return new_head;
// as well as
Node* new_node = new Node(data);
curr->next = new_node;
All nodes must be create on the free store (with new), otherwise they get cleaned up when the function ends.
This means you are always referencing to not existing variables, which is a memory corruption. You must as well provide a destructor to delete the new'd nodes.
For more information read about the lifespan of variables.
Further notes:
use nullptr
std::list, or std::linked_list are the containers for lists (i know, you want to learn, but take a look at them)
your class is all public -> you can use a struct, since its the same, but default public for access specifiers.
use unique_ptr for the ownership (this is kinda advanced, but use it early)
I am having two issues with my c++ code (The test file is below):
I can't seem to figure out why its not breaking out of the while loop, when running, its stuck on the loop "7 versus 325".
So it should go into the next node of temp, which would be null, and then jump into the section where it adds it to the end of the queue. But its just looping and looping.
My second issue is with the the function I have commented out, queue1.back, whenever that is ran, it just errors out and gives what appears to be the address, but the .front() function works just fine.
The Test File I am working with is like this:
89 Alex
325 Rob
72 Joy
91 Bob
using namespace std;
class Person
{
friend class Pqueue;
public:
int priority;
string name;
};
class PQueue
{
friend class Person;
private:
//Structure for my linked list.
typedef struct node {
Person data;
struct node *next;
}Node, *NodePtr;
Node *head, *tail;
public:
//Prototype Functions
PQueue(void); //Initializer function
bool empty(void); //Test if empty
int size(void); //Return size
void enqueue(Person *); //Insert Node
void dequeue(void); //Remove Node
Person* front(void); //Access Next Node
Person* back(void); //Access last node
};
PQueue::PQueue()
{
head = NULL;
tail = NULL;
}
bool PQueue::empty(){
return (head == NULL);
}
void PQueue::enqueue(Person *myPerson){
NodePtr np = (NodePtr) malloc(sizeof(Node));
np->data = *myPerson;
np->next = NULL;
if(empty())
{
cout << "Making into creating the first node, of the linked list" <<endl;
head = np;
tail = np;
}
else { //Queue has more the one node
Node* temp = head;
if(np->data.priority > temp->data.priority) //If the priority is greater then the rest.
{
head = temp; //Saving my head pointer
head->data = np->data; //Assigning new Data to the head pointer
head->next = temp; //Assigning the rest of the linked list back into head.
cout << "Making into creating the first node again, having to reassign." <<endl;
}
else{
//Searching where to place the node.
while(temp->data.priority > np->data.priority) //Searching if the next priority is higher then the passed.
{
cout << "Inside the while loop: " << np->data.priority << " versus "<<temp->data.priority <<endl;
if(temp->next == NULL)
break;
temp = temp->next;
}
if(temp->next == NULL && np->data.priority < temp->data.priority) //Inserting at the end.
{
cout << "Making into creating the last node" <<endl;
tail->next = np;
cout << "Passing the function of creating the last node" <<endl;
}
else //Inserting into the middle of the function.
{
cout << "Inserting in the middle of the queue" <<endl;
np->next = temp->next;
temp->next = np;
}
}
}
}
void PQueue::dequeue(){
if(empty()){
cout << "\nAttempt to remove from an empty list." << endl;
exit(1);
}
Person hold = head->data;
NodePtr temp = head;
head=head->next;
if (head == NULL) tail = NULL;
free(temp);
}
Person* PQueue::front(){
//Person &temp = head->next->data;
//Person &temp = head->data;
Person &temp = head->data;
return &temp;
}
Person* PQueue::back(){
if(empty()){
cout << "\nNo entries in list." << endl;
exit(1);
}
Person &temp = tail->data;
return &temp;
}
int main() {
cout << "Starting main" << endl;
PQueue queue1; //Creating my queue.
cout << "Created Queue" << endl;
Person tempPerson;
ifstream inFile;
inFile.open("/tmp/temp");
cout << "going into while loop" << endl;
while (inFile >> tempPerson.priority >> tempPerson.name){
cout << "The priority is " << tempPerson.priority << " the name is " << tempPerson.name <<endl;
queue1.enqueue(&tempPerson);
}
//Testing Section, trying to get .front and .back to work.
Person *testPerson;
testPerson = queue1.front();
cout << "The TEST priority is " << testPerson->priority << " the TEST name is " << testPerson->name <<endl;
/**
Person *tailPerson;
testPerson = queue1.back();
cout << "The TEST priority is " << tailPerson->priority << " the TEST name is " << tailPerson->name <<endl;
**/
queue1.dequeue();
queue1.dequeue();
queue1.dequeue();
return 0;
}
When you add a new head entry to a non-empty list, you're mistakenly setting the next pointer to point right back at the node it's in, rather than setting it to point at the rest of the linked list like you intended.
head = temp; //Saving my head pointer
head->next = temp; //Assigning the rest of the linked list back into head.
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;