Enqueue successful, but Queue prints nothing? - c++

I am trying to enqueue data into a queue.
The enqueue appears to have been successful because the current Node's Thing pointer is not null. Indeed, its Thing id is 7 as expected. However, something is wrong with ThingQueue's print function because the exact same Node is identified as a nullptr. This is despite the fact that both the enqueue and print functions iterate through the queue in the same way. Can anybody explain the discrepancy?
Here is a minimal reproducible example of my problem:
#include <iostream>
using namespace std;
struct Thing
{
int id;
Thing()
{
id = 7;
}
void print()
{
cout << "Thing " << to_string(id) << " ";
}
};
class ThingQueue
{
public:
ThingQueue()
{
front = nullptr;
}
void enqueue(const Thing &thing)
{
cout << "Attempting to enqueue..." << endl;
Node *curr = front;
while (curr != nullptr) curr = curr->next;
curr = new Node;
curr->next = nullptr;
curr->thing = (Thing*) &thing;
cout << "Is curr->thing nullptr? 1 for true, 0 for false: ";
cout << to_string(curr->thing == nullptr) << endl;
cout << "curr->thing->id = " << to_string(curr->thing->id) << endl;
}
void print()
{
cout << "Attempting to print..." << endl;
Node *curr = front;
cout << "Is curr nullptr? 1 for true, 0 for false: ";
cout << to_string(curr == nullptr) << endl;
while (curr != nullptr) {
curr->thing->print();
curr = curr->next;
}
}
private:
struct Node
{
Node *next;
Thing *thing;
};
Node *front;
};
int main() {
Thing *pThing = new Thing();
ThingQueue *pThingQueue = new ThingQueue();
pThingQueue->enqueue(*pThing);
pThingQueue->print();
std::cout << std::endl;
return 0;
}
Output:
Attempting to enqueue...
Is curr->thing nullptr? 1 for true, 0 for false: 0
curr->thing->id = 7
Attempting to print...
Is curr nullptr? 1 for true, 0 for false: 1
SOLUTION:
Thanks for all the tips and feedback. After working out the remaining bugs and feedback, I have a minimum reproducible example that compiles, runs and produces the expected output! (Not worrying about memory management for this example)
#include <iostream>
using namespace std;
struct Thing
{
int id;
Thing()
{
id = 7;
}
void print()
{
cout << "Thing " << to_string(id) << " ";
}
};
class ThingQueue
{
public:
ThingQueue()
{
front = nullptr;
}
void enqueue(const Thing &thing)
{
if (front == nullptr)
{
// queue is empty, set front to new node
front = new Node;
front->next = nullptr;
front->thing = thing;
}
else
{
// queue is not empty, find last node
Node* curr = front;
while (curr->next != nullptr)
curr = curr->next;
// curr now points to the last node, set curr->next to new node
curr->next = new Node;
curr->next->next = nullptr;
curr->next->thing = thing;
}
}
void print()
{
Node *curr = front;
while (curr != nullptr) {
curr->thing.print();
curr = curr->next;
}
}
private:
struct Node
{
Node *next;
Thing thing;
};
Node *front;
};
class Stuff
{
};
int main() {
Thing thing = Thing();
Thing thing2 = Thing();
Thing thing3 = Thing();
ThingQueue tq = ThingQueue();
tq.enqueue(thing);
tq.enqueue(thing2);
tq.enqueue(thing3);
tq.print();
return 0;
}

Look at enqueue, it creates a new Node and sets curr to point at it. But curr is a variable in the enqueue function, it has nothing to do with your queue, as soon as the enqueue function is exited the curr variable is lost.
You also have another problem. For some reason you have made thing a pointer. This means you end up with pointers to variables which have been destroyed. Change thing to be a non-pointer.
Here's how enqueue should look.
void enqueue(const Thing &thing)
{
if (front == nullptr)
{
// queue is empty, set front to new node
front = new Node;
front->next = nullptr;
front->thing = thing;
}
else
{
// queue is not empty, find last node
Node* curr = front;
while (curr->next != null)
curr = curr->next;
// curr now points to the last node, set curr->next to new node
curr->next = new Node;
curr->next->next = nullptr;
curr->next->thing = thing;
}
}
I can see you are suffering from the pointers everywhere syndrome that beginners sometimes have.
Here's main rewritten without all the unnecessary pointers
int main() {
Thing thing;
ThingQueue thingQueue;
thingQueue.enqueue(thing);
thingQueue.print();
std::cout << std::endl;
return 0;
}
The only pointers you need in this code are the next field in your node class, the front member in your queue class, and the curr variable.

Related

Unhandled exception thrown: read access violation. "this" was 0x8 - Using Shared_ptr

Node.h
#pragma once
#include <iostream>
#include<memory>
class Node
{
public:
Node();
Node(int k, int d);
int key;
int data;
std::shared_ptr<Node> next;
std::shared_ptr<Node> previous;
//Node* next;
//Node* previous;
};
doubleLinkedList.h
#pragma once
/*! \class Double Linked List
\brief A double linked list data structure
*/
#include <iostream>
#include "../Node.h"
#include <string>
#include<memory>
class DoubleLinkedList : public Node
{
private :
std::shared_ptr<Node> head; //Node* head;
std::shared_ptr<Node> temp; //Node* temp;
std::shared_ptr<Node> mypointer; //Node* ptr;
std::shared_ptr<Node> nextNode;
std::shared_ptr<Node> prevNode;
public :
DoubleLinkedList();
DoubleLinkedList(std::shared_ptr<Node> n);
std::shared_ptr<Node> checkNodeExsits(int k); //Node*
void addNodeToFront(std::shared_ptr<Node> n); //Node*
void addNodeToEnd(std::shared_ptr<Node> n); //Node*
void addNodeAfter(int k, std::shared_ptr<Node> n); //Node*
void UpdateNode(int k , int d);
void deleteNode(int k);
void printList();
void printInfo(std::string Info);
};
Node.cpp
#include "Node.h"
#include <iostream>
Node::Node()
{
key = 0;
data = 0;
next = nullptr;
previous = nullptr;
}
Node::Node(int k, int d)
{
key = k;
data = d;
}
doubleLinkedList.cpp
#include <iostream>
#include "include\doubleLinkedList.h"
DoubleLinkedList::DoubleLinkedList()
{
head = nullptr;
}
DoubleLinkedList::DoubleLinkedList(std::shared_ptr<Node> n)
{
head = n;
}
std::shared_ptr<Node> DoubleLinkedList::checkNodeExsits(int k)
{
temp = nullptr;
mypointer = head;
while (mypointer != nullptr) {
if (mypointer -> key == k) {
temp = mypointer;
}
mypointer = mypointer-> next;
}
return temp;
}
void DoubleLinkedList::addNodeToFront(std::shared_ptr<Node> n)
{
if (checkNodeExsits(n->key) != nullptr)
{
printInfo("Node Already exist with key Number ");
}
else {
if (head == nullptr) {
head = n;
printInfo("Node Added as Head Node");
}
else {
head->previous = n;
n->next = head;
head = n;
printInfo("Node Added To The Begining");
}
}
}
void DoubleLinkedList::addNodeToEnd(std::shared_ptr<Node> n)
{
if (checkNodeExsits(n->key) != nullptr)
{
printInfo("Node Already exist with key Number");
}
else {
if (head == nullptr)
{
head = n; // if there isnt any node in the list.
printInfo("Node Has Been Added As Head Node");
}
else {
mypointer = head;
while (mypointer ->next != nullptr)
{
mypointer = mypointer->next;
}
mypointer->next = n;
n->previous = mypointer;
printInfo("Node Has Been Added To The End");
}
}
}
void DoubleLinkedList::addNodeAfter(int k, std::shared_ptr<Node> n)
{
mypointer = checkNodeExsits(k);
if (mypointer == nullptr) {
printInfo("No Node Exists With The Key Value");
}
else {
if (checkNodeExsits(n -> key) != nullptr) {
printInfo("Node Already exist with key Number");
}
else {
nextNode = mypointer-> next;
// inserting at the end
if (nextNode == nullptr) {
mypointer-> next = n;
n -> previous = mypointer;
printInfo("Node Inserted at the END");
}
//inserting in between
else {
n -> next = nextNode;
nextNode -> previous = n;
n -> previous = mypointer;
mypointer-> next = n;
printInfo("Node Inserted in Between");
}
}
}
}
void DoubleLinkedList::UpdateNode(int k, int d)
{
mypointer = checkNodeExsits(k);
if (mypointer != nullptr) {
mypointer-> data = d;
std::cout << "Node Data Updated Successfully" << std::endl;
}
else {
std::cout << "Node Doesn't exist with key value : " << k << std::endl;
}
}
void DoubleLinkedList::deleteNode(int k)
{
mypointer = checkNodeExsits(k);
if (mypointer == nullptr) {
std::cout << "No node exists with key value: " << k << std::endl;
}
else {
if (head -> key == k) {
head = head -> next;
std::cout << "Node UNLINKED with keys value : " << k << std::endl;
}
else {
nextNode = mypointer-> next;
prevNode = mypointer-> previous;
// deleting at the end
if (nextNode == nullptr) {
prevNode -> next = nullptr;
std::cout << "Node Deleted at the END" << std::endl;
}
//deleting in between
else {
prevNode -> next = nextNode;
nextNode -> previous = prevNode;
std::cout << "Node Deleted in Between" << std::endl;
}
}
}
}
void DoubleLinkedList::printList()
{
if (head == nullptr) {
std::cout << "No Nodes in Doubly Linked List";
}
else {
std::cout << std::endl << "Doubly Linked List Values : ";
temp = head;
while (temp != nullptr) {
std::cout << "[Key: " << temp->key << ", Data: " << temp->data << "] <___> " << std::endl;
temp = temp -> next;
}
}
}
void DoubleLinkedList::printInfo(std::string Info)
{
std::cout << Info << std::endl;
}
main.cpp
#include <iostream>
#include "../include/doubleLinkedList.h"
#include"../Node.h"
void Print(std::string info)
{
std::cout << info << std::endl;
}
int main() {
DoubleLinkedList myNode;
//Node* newNode = new Node(2,7);
std::shared_ptr<Node> newNode = std::make_shared<Node>(2, 7); // enter key number and data number
std::shared_ptr<Node> newNode1 = std::make_shared<Node>(3, 9);// enter key number and data number
newNode->key;
newNode->data;
myNode.addNodeToFront(newNode);
newNode->key;
newNode->data;
myNode.addNodeAfter(2, newNode1); // enter the key number of existing node and then to add new key number and new data
myNode.printList();
system("pause");
return 0;
}
The error I'm getting is:
unhandled exception thrown: read access violation. "this" was 0x8
To elaborate -
( Access violation reading location 0x0000000000000010. Unhandled exception thrown: read access violation).
So, the code would work when I use raw pointers. The only thing I can deduce from this is that there's a chain of shared pointers in the method of void DoubleLinkedList::addNodeAfter() nextNode = mypointer-> next;
or that shared pointers can't have nullptr assigned to it.
I'm clueless as to why this is happening.
Let's take a walk through addNodeAfter
mypointer = checkNodeExsits(k);
We've checked to make sure value k exists in the list and gotten a pointer to it if it does. If it doesn't, we get a null pointer.
if (mypointer == nullptr) {
Tests whether or not k was found. Let's assume it was, mypointer isn't null, and we enter the else
else {
if (checkNodeExsits(n -> key) != nullptr) {
Here we check to make sure the node we're inserting isn't a duplicate. Again let's take the else branch
else {
nextNode = mypointer-> next;
Should be safe, right? We know that mypointer was not null because we tested it earlier. But when we look... Holy smurf! The program crashed! It was null. How did it become null?
The answer lies in another question: Where did mypointer come from? It's not defined within this function, so it has wider scope. Turns out it is a DoubleLinkedList member variable. Is someone else messing with it? We don't have multiple threads, so it must be another function that was called by addNodeAfter.
That would have to be checkNodeExsits, so let's take a look at it.
std::shared_ptr<Node> DoubleLinkedList::checkNodeExsits(int k)
{
temp = nullptr;
mypointer = head; // well lookie here!
while (mypointer != nullptr) {
if (mypointer -> key == k) {
temp = mypointer;
}
mypointer = mypointer-> next; // and here!
}
return temp;
}
We can see that if the inserted node's value does not exist, thus putting us in the else case back in addNodeAfter where we're going to insert the new node, mypointer can only be null!
The overly broad scope of mypointer turns the member variable into a boobytrap. It needs to be a variable local to checkNodeExsits and addNodeAfter to prevent these functions from trashing the state of the functions that use them. This leads to questioning whether mypointer should be a member variable anywhere it is found. That leads to wondering about temp, nextnode and prevnode. They all sound like temporary holders of local state information. Likely the only DoubleLinkedList member that should be a member is head.
To fix: Remove the definition of mypointer from the class and resolve the compiler errors that result. If a use of mypointer can be easily replaced with a local variable, do so. For any that remain and are needing of longer-term storage for resuse, you'll have to get a bit more creative. Make the call on how long-lived and how wide a scope is necessary to get the behaviour you want and then give this new variable an appropriately descriptive name to help you remember the circumstances in which it should be used.
I recommend repeating this process for the other member variables except for head where the necessary scope and lifetime is obvious.
General rule of thumb: Keep the scope of variables as tight as possible. Only widen the scope of a variable if you absolutely need to reuse its state later, and if you find you must be very careful with it to ensure you don't cause unintended side-effects.

Why is there an access violation error when trying to access reference pointer?

I'm trying to make single linked list's fucntions.
but it reports an error. like this..
i am trying to a lot of thing about that.
like using rvlaue reference, double pointer
but nothings work..
what is the problem?
and can i return p pointer in getNode(int k) fucntion?
#include<iostream>
using namespace std;
template<typename T>
class SingleLList {
private:
template<typename T>
struct Node {
T data;
Node<T>* next;
};
Node<T>* head;
int size; // for List size
public:
SingleLList() :head(nullptr) {};
~SingleLList() {
Node<T>* delNode;
while (head->next != nullptr) {
delNode = head;
head = head->next;
delete delNode;
}
};
// add Node at index th
void addNode(int index, T data) {
if (index < 0)return;
Node<T>* newNode = new Node<T>;
newNode->data = data;
newNode->next = nullptr;
if (index == 0) { // add at 0
// empty
if (head == nullptr) head = newNode;
// not empty
else {
newNode->next = head->next;
head = newNode;
}
size++;
}
else {
Node<T>* prev = head;
for (int i = 1; i < index && prev != nullptr; i++) {
prev = prev->next;
}
newNode->next = prev->next;
prev->next = newNode;
size++;
}
}
// traversa
void showList()const {
Node<T>* p = head;
cout << "Single Linked List : [ ";
while (p != nullptr) {
cout << p->data << " ";
p = p->next;
}
cout << " ]" << "total elements are : "
<< size << endl;
}
// return k th Node by reference.
Node<T>*& getNode(int k)const {
if (head == nullptr || k > size) {
Node<T>* temp = nullptr;
return temp;
}
// Node<T>* p; < -- is it okay?
Node<T>* p = new Node<T>;
p= head;
for (int i = 1; i < k && p->next != nullptr; i++) {
p = p->next;
}
cout << " address of p : " << &p << endl;
cout << "value of p : " << p << endl;
return p;
}
// delete n Node in list
void deleteNode(Node<T>*& n) {
cout << "address of n : " << &n << endl;
cout << n->data << endl;
if (n->next == nullptr) { // if last node
delete n->next;
n = nullptr; //
size--;
}
else {
Node<T>* del_node = n->next;
n->data = n->next->data;
n->next = n->next->next;
delete del_node;
size--;
}
}
};
int main() {
SingleLList<int> sll;
sll.addNode(0, 4);
sll.addNode(1, 5);
sll.addNode(2, 6);
sll.addNode(3, 8);
sll.addNode(4, 9);
sll.showList();
sll.deleteNode(sll.getNode(5));
sll.showList();
return 0;
}
and in main i make Linked List like this.
Node<T>*& getNode(int k)const {
if (head == nullptr || k > size) {
Node<T>* temp = nullptr;
return temp;
This same basic bug occurs several times in the shown code. All instances of this bug will need to be fixed.
temp is a local variable. Once this function returns, it goes out of scope and gets destroyed.
However: this function is declared as returning a reference to a pointer, and by returning temp this ends up returning a reference to an object that's already destroyed, when the function returns. All subsequent use of this reference automatically becomes undefined behavior, and the likely reason for your crash. For example:
sll.deleteNode(sll.getNode(5));
For example, getNode() returns a reference here. To add insult to injury this reference isn't even used immediately, but it gets passed to deleteNode(). By that time temp, or a reference to whatever was originally returned from getNode, is a distant memory and was already destroyed a long, long time ago, and attempting to reference it will not end well.
There are likely other issues, but this is fundamental, and fixing it will require fundamental changes to the shown logic, as such the first order of business will be to redesign the shown code, and it will likely involve other major changes to the rest of the code, as well.

Linked list search function modifying list

I am trying to implement a doubly linked list in C++ and the add function is working properly but the find node function is modifying the list.
All other function like insertAfter, delete depend on this find function and hence they are also not working as expected.
I am new to C++, so I don't completely understand pointers. I simply tried to replicate my Java program in C++. I know for sure that in the find function the pointer to the head node is causing the problem but I don't completely understand how.
Below is my code :
struct Node{
int data;
Node* next;
Node* prev;
Node(int d) {
data = d;
};
};
struct DLL {
Node* head;
Node* tail;
int size;
//Adding a Node to the Doubly LL
void addNode(Node* n) {
//If LL is empty add the first Node
if (tail == NULL) {
tail = n;
head = n;
}
//Else add add node to the tail. Connect n to the tails next and make n the tail
else {
tail->next = n;
n->prev = tail;
tail = n;
tail->next = NULL;
}
size++;
};
//Finding a random Node in the linked List
//It will return the Node with the FIRST occurrence where data = d
Node* findNode(int d) {
//We will start at the head and then traverse through the entire list to find a Node where data = d
Node* start = head;
if (start == NULL) {
cout<<"No element in the List" <<endl;
return NULL;
}
// If head is the Node we are looking for
if (start->data = d) {
cout<< "Node found with matching data : " << start << endl;
return start;
}
//While next pointer is not null, traverse to search for a match.s
while (start->next != NULL) {
start = start->next;
if (start->data == d) {
cout<< "Node found with matching data : " << start << endl;
return start;
}
}
cout << "No node found with matching data = " << d <<endl;
return NULL;
};
};
start->data = d
This line in your second if block is assigning d to start->data rather than comparing the two.
This is a good time to learn about constness.
Node* findNode(int d) {
//We will start at the head and then traverse through the entire list to find a Node where data = d
Node* start = head;
if (start == NULL) {
cout<<"No element in the List" <<endl;
return NULL;
}
// If head is the Node we are looking for
if (start->data = d) {
cout<< "Node found with matching data : " << start << endl;
return start;
}
This function has write access to the list, and you don't want that. Unfortunately, you abuse this access in the last if statement:
if (start->data = d) {
this code assigns the value of d to start->data and then tests if the value assigned to it was not null.
We can mark this function as const easily:
//////////////////////vvvvv/////////////////
Node* findNode(int d) const {
//We will start at the head and then traverse through the entire list to find a Node where data = d
Node* start = head;
if (start == NULL) {
cout<<"No element in the List" <<endl;
return NULL;
}
// If head is the Node we are looking for
if (start->data = d) {
cout<< "Node found with matching data : " << start << endl;
return start;
}
and now the if will generate a compiler error.
A cleaned up version of your code might look something like the following:
#include <iostream>
struct Node {
int data_;
Node* next_ { nullptr };
Node* prev_ { nullptr };
Node(int data) : data_(data) {}
};
struct DLL {
Node* head_ { nullptr };
Node* tail_ { nullptr };
int size_ { 0 };
//Adding a Node to the Doubly LL
void addNode(Node* node) {
//If LL is empty add the first Node
if (tail_ == nullptr) {
tail_ = node;
head_ = node;
node->prev_ = node->next_ = nullptr;
}
//Else add add node to the tail. Connect n to the tails next and make n the tail
else {
tail_->next_ = node;
node->prev_ = tail_;
tail_ = node;
node->next_ = nullptr;
}
size_++;
}
//Finding a random Node in the linked List
//It will return the Node with the FIRST occurrence where data = d
Node* findNode(int data) const {
//We will start at the head and then traverse through the entire list to find a Node where data = d
//While next pointer is not null, traverse to search for a match.s
for (Node* start = head_; start != nullptr; start = start->next_) {
if (start->data_ == data) {
std::cout << "Node found with matching data : " << start << '\n';
return start;
}
}
std::cout << "No node found with matching data = " << data << '\n';
return nullptr;
}
};
int main()
{
DLL dll;
Node n1(1), n3(3), n5(5);
dll.addNode(&n1);
dll.addNode(&n3);
dll.addNode(&n5);
if (dll.findNode(1) != &n1)
std::cerr << "wrong result for findNode(1)\n";
if (dll.findNode(2) != nullptr)
std::cerr << "wrong result for findNode(2)\n";
if (dll.findNode(3) != &n3)
std::cerr << "wrong result for findNode(3)\n";
if (dll.findNode(4) != nullptr)
std::cerr << "wrong result for findNode(4)\n";
if (dll.findNode(5) != &n5)
std::cerr << "wrong result for findNode(5)\n";
}
Live demo: http://ideone.com/X34EgY

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;

Bubble sort Linked list C++

I'm having problems with this code. I'm pretty sure it's in the swapping.
The line: curr->Data() = nextEl.Data() gives me the following error:
"expression must be a modifiable lvalue"
Any help is appreciated. Thank you in advance.
Here is the code for my bubble-sort algorithm:
class Node
{
private:
int data;
Node* next;
public:
Node() {};
void Set(int d) { data = d;};
void NextNum(Node* n) { next = n;};
int Data() {return data;};
Node* Next() {return next;};
};
class LinkedList
{
Node *head;
public:
LinkedList() {head = NULL;};
virtual ~LinkedList() {};
void Print();
void AddToTail(int data);
void SortNodes();
};
void LinkedList::SortNodes()
{
Node *curr = head;
Node *nextEl = curr ->Next();
Node *temp = NULL;
if(curr == NULL)
cout <<"There is nothing to sort..."<< endl;
else if(curr -> Next() == NULL)
cout << curr -> Data() << " - " << "NULL" << endl;
else
{
for(bool swap = true; swap;)
{
swap = false;
for(curr; curr != NULL; curr = curr ->Next())
{
if(curr ->Data() > nextEl ->Data())
{
temp = curr ->Data();
curr ->Data() = nextEl ->Data();
nextEl ->Data() = temp;
swap = true;
}
nextEl = nextEl ->Next();
}
}
}
curr = head;
do
{
cout << curr -> Data() << " - ";
curr = curr -> Next();
}
while ( curr != NULL);
cout <<"NULL"<< endl;
}
You are doing it wrong. You cannot change the value of temp variable returned by a function.
But you can make it work this way..
int& Data() {return data;};
though this is not good practise. Instead just use the setter you have..
curr->Set(nextEl->Data());
The statement
curr->Data() = nextEl.Data();
will never work, you are trying to assign something to the return value of a function. I don't know how you defined Node, but you probably meant something like
curr->Data = nextEl.Data();
i.e., assign something to a member of Node.
change
curr ->Data() = nextEl ->Data();
nextEl ->Data() = temp;
to
curr->Set(nextEl ->Data());
nextEl->Set(temp);