I am trying to create a binary tree that when you try to add a new node to that, it adds the node to first position that is nullptr.
actually making a complete binary tree.
Look at the code below:
#include <iostream>
#include <queue>
using namespace std;
class node{
private:
char data;
node* right;
node* left;
public:
node(char n){
data = n;
left = nullptr;
right = nullptr;
}
char getdata(){
return data;
}
friend class binTree;
};
class binTree{
private:
node *root;
public:
binTree(){
root = nullptr;
}
binTree(node *root){
this->root = root;
}
node* getRoot(){
return this->root;
}
void addNode(char data){
cout << "adding " << data << endl;
if(root == nullptr) {
root = new node(data);
return;
}
queue<node*> Q;
Q.push(root);
node* toadd;
while(true) {
node* toadd = Q.front();
Q.pop();
Q.push(toadd->left);
Q.push(toadd->right);
if(toadd->left == nullptr) break;
if(toadd->right == nullptr) break;
}
if((toadd->left) == nullptr)
{
cout << "add data to the left of " << toadd -> data << endl;
toadd->left = new node(data);
} else if((toadd -> right) == nullptr){
cout << "add data to the right of " << toadd -> data << endl;
toadd->right = new node(data);
} else {
cout << "toadd left and right are not nullptr" << endl;
}
}
};
int main()
{
binTree bin;
string s = "abcdefg";
cout << s << endl << endl;
for(int i = 0; i < s.size(); i++)
{
bin.addNode(s[i]);
}
}
when I run this code the output is:
abcdefg
adding a
adding b
toadd left and right are not nullptr
adding c
toadd left and right are not nullptr
adding d
toadd left and right are not nullptr
adding e
toadd left and right are not nullptr
adding f
toadd left and right are not nullptr
adding g
toadd left and right are not nullptr
the strange part is when printing "toadd left and right are not nullptr"
because there is a while(true) and the only exit conditions are:
if(toadd->left == nullptr) break;
if(toadd->right == nullptr) break;
so one of these conditions were true that we could break the loop;
so we should enter one of if or else if part of the following code (after the while) but surprisingly we enter the else part and end of printing "toadd left and right are not nullptr".
can anyone explain this behavior?
You've defined toadd twice, once before the loop and once inside. Easy mistake to make.
Related
This question already has answers here:
Function does not change passed pointer C++
(4 answers)
Closed 9 months ago.
https://leetcode.com/problems/flatten-binary-tree-to-linked-list/
i am talking about function "flatten", I know i can do it without making another function named help but I want to do this question this way. The help function is flattening the tree correctly and returning it correctly in TreeNode* ans, but it is not reflecting in root, in root it is printing from original
using namespace std;
class TreeNode {
public:
int val;
TreeNode *left;
TreeNode *right;
TreeNode(int val) {
this->val = val;
left = right = nullptr;
}
};
TreeNode *takeInput() {
int rootData;
cout << "Enter data of root node" << endl;
cin >> rootData;
if (rootData == -1) {
return nullptr;
}
TreeNode *root = new TreeNode(rootData);
queue<TreeNode *> pendingNodes;
pendingNodes.push(root);
while (!pendingNodes.empty()) {
TreeNode *front = pendingNodes.front();
pendingNodes.pop();
int leftNodeData;
cout << "Enter val of left child of parent " << front->val << endl;
cin >> leftNodeData;
if (leftNodeData != -1) {
front->left = new TreeNode(leftNodeData);
pendingNodes.push(front->left);
}
int RightNodeData;
cout << "Enter val of Right child of parent " << front->val << endl;
cin >> RightNodeData;
if (RightNodeData != -1) {
front->right = new TreeNode(RightNodeData);
pendingNodes.push(front->right);
}
}
return root;
}
void print(TreeNode *root) {
if (root == NULL) {
return;
}
queue<TreeNode *> pendingNodes;
pendingNodes.push(root);
while (!pendingNodes.empty()) {
TreeNode *front = pendingNodes.front();
pendingNodes.pop();
cout << front->val << ":";
if (front->left != nullptr) {
cout << " L: " << front->left->val;
pendingNodes.push(front->left);
}
if (front->right != nullptr) {
cout << " R: " << front->right->val;
pendingNodes.push(front->right);
}
cout << endl;
}
}
TreeNode *help(TreeNode *root) {
if (root == nullptr) {
return nullptr;
}
TreeNode *leftAns = help(root->left);
TreeNode *rightAns = help(root->right);
if (leftAns != nullptr) {
TreeNode *temp = leftAns;
while (temp->right != nullptr) {
temp = temp->right;
}
temp->right = root;
root->left = nullptr;
}
root->right = rightAns;
if (leftAns != nullptr) {
root = leftAns;
return leftAns;
}
return root;
}
void flatten(TreeNode *root) {
TreeNode *ans = help(root);
// help(root);
// *root = *ans;
root = ans;
// root = help(root);
}
int main() {
TreeNode *root = takeInput();
print(root);
flatten(root);
cout << "ans:" << endl;
print(root);
return 0;
}```
As user207421 stated in his comment, you are currently passing root into the flatten function by value meaning that when root is assigned the value of ans in the line
root = ans;
Only the local copy of root is being altered. If you passed root into the function by reference, the value of the root value would be changed rather than just a local copy.
The function would simply need to be changed to
void flatten(TreeNode *&root) {
root = help(root);
}
Edit:
Having looked over the leet code link I now realize the previous answer is invalid for doesn't exactly match the provided flatten function signature given in the challenge. I will leave the original answer above in case it is useful. If you wish to change the value of root, you should assign the value pointed to by answer to the memory location pointed to be root
void flatten(TreeNode *root) {
*root = *help(root);
}
I am new to programming in C++ but I am trying to create a Binary Search Tree.
The program seems to compile fine but it gives me this error:
Unhandled exception at 0x009229B7 in Lab001_CS3.exe: 0xC00000FD: Stack
overflow (parameters: 0x00000001, 0x00AD2FBC).
when I try to run it. The error occurs on this line of code:
void insert(int value) {
...
}
I am not sure what I am doing wrong, and I have never gotten this error before.
Here is the code:
#include <iostream>
using namespace std;
//create a node struct
struct node {
//member variables
int key;
node* left;
node* right;
//default constructor
node() {
key = 0;
left = NULL;
right = NULL;
cout << "a new node is created" << endl;
}
//constructor so can create a node in one line
node(int k) {
key = k;
left = NULL;
right = NULL;
cout << "a new node is created" << endl;
}
};
class Tree {
public:
//root node
node root;
//default constructor
Tree() {
root.key = 0;
root.left = NULL;
root.right = NULL;
}
//constructor to create the root node
Tree(int data) {
//set the data to the key
//set the right and left pointers to null
root.key = data;
root.left = NULL;
root.right = NULL;
}
//print the root node
void printRootNode() {
cout << "Root Node - Key: " << root.key << endl;
}
//insert functions
void insert(int value) {
/* If the newNode's key is less than the root key, traverse left
*/
if (value < root.key) {
/* if the left node is NULL */
if (root.left == NULL) {
root.left = new node(value);
cout << "assigned left" << endl;
}
else {
/* if the left node is important */
insert(value);
cout << "recurse" << endl;
}
}
if (value > root.key) {
/* if the right node is NULL */
if (root.right == NULL) {
root.right = new node(value);
cout << "assigned right" << endl;
}
else {
/* if the right node is important */
insert(value);
cout << "recurse" << endl;
}
}
}
};
//print inorder
void inorder(node* rt) {
//base
if (rt == NULL) {
return;
}
inorder(rt->left);
cout << " " << rt->key << endl;
inorder(rt->right);
}
int main() {
//create a tree for a root node
Tree t(16);
t.printRootNode();
//create newNode
node n1(20);
node n2(31);
//insert the new nodes
t.insert(20);
t.insert(31);
//keep the window from closing
system("pause");
}
Thank you for any help.
In your insert()
if (value < root.key) {
/* if the left node is NULL */
if (root.left == NULL) {
root.left = new node(value);
cout << "assigned left" << endl;
}
else {
/* if the left node is important */
insert(value);
cout << "recurse" << endl;
}
}
let's take this go left snippet as example, if root.left != NULL the code will enter else block and recursively call insert(value) forever, which cause stack overflow, the correct operation is make current node move to root.left, and then call insert(value) recursively.
also you don't need node class at all, tree class can do all the things.
again, here is not a good place for help you debug, you need to learn how to do this yourself :-).
The code bellow inserts nodes correctly but
I have a problem that when try to print the list the program unfortunately stop working.
The error message is : your project has stopped working.
This is my code:
#include <iostream>
#include <string>
using namespace std;
typedef struct st {
string data;
int ISBN;
string Title;
string Author;
int publishedyear;
bool borrow;
st* next;
} NODE;
NODE* add(NODE* head, int isbn)
{
NODE *p1, *p2;
NODE* n;
n = new NODE;
n->ISBN = isbn;
if (head == NULL) {
head = n;
return head;
}
if (n->ISBN < head->ISBN) {
n->next = head;
head = n;
return head;
}
p1 = p2 = head;
while (p2 != NULL) {
if (n->ISBN < p2->ISBN) {
n->next = p2;
p1->next = n;
return head;
}
else {
p1 = p2;
p2 = p2->next;
}
}
n->next = p2;
p1->next = n;
return head;
}
void print(NODE* head)
{
NODE* p;
p = head;
if (head == NULL) {
cout << "empty list" << endl;
}
while (p != NULL) {
cout << "Book ISBN Is : " << p->ISBN << endl;
p = p->next;
}
}
void main()
{
// cout << "hi";
NODE* head;
head = NULL;
string op;
int isbn;
cout << "Enter the opertion in the following format : op , ISBN" << endl;
while (1) {
cin >> op;
if (op == "add") {
cin >> isbn;
if (op == "add") {
head = add(head, isbn);
cout << "book with thie ISBN code " << isbn << " is added successfuly."
<< endl;
}
}
else if (op == "print") {
print(head);
}
else {
cout << "Enter vaild operation! ." << endl;
}
}
}
any suggestions ?
The answer was pointed out, but... I feel awfully unsatisfied by the state of your code, so allow me to give you a few tips.
Note: unless the point is to build a list, do reuse the existing standard containers (vector, in particular) and algorithms (sort) rather than building your own.
Let's start with the basics, this is the year 2016 you should have access to C++11 by now.
C++11 allows to initialize data-members straight at the point of declaration, and I recommend that you do it for all built-in types (integrals, booleans, floating points and pointers) since by default they otherwise contain garbage which is puzzling.
struct Node {
std::string data;
int ISBN = 0;
std::string title;
std::string author;
int publishedyear = 0;
bool borrow = false;
Node* next = nullptr;
};
Note that this alone solves your bug. And it also avoids forgetting it the next time.
Secondly, the add method should NOT be responsible for creating a node. This is mixing concerns, and it also leaves most of the node with default values and no way to access it without looking for it by its ISBN.
There's also a point that the add method does not account for: what if the ISBN is already in the list?
// Adds the new node to the list, maintaining the ordering by ISBN.
//
// Returns the new head of the list, unless an existing node in the list already
// has this ISBN in which case returns `nullptr`.
Node* add(Node* head, Node* node) {
assert(node != nullptr && "Null argument provided");
if (head == nullptr) {
return node;
}
if (node->ISBN < head->ISBN) {
node->next = head;
return node;
}
if (node->ISBN == head->ISBN) {
return nullptr;
}
// Find "current" such that "current->ISBN" < "node->ISBN" and
// "node->ISBN" <= "current->next->ISBN"
Node* current = head;
while (current->next != nullptr && node->ISBN > current->next->ISBN) {
current = current->next;
}
if (node->ISBN == current->next->ISBN) {
return nullptr;
}
node->next = current->next;
current->next = node;
return head;
}
Note: assert requires #include <cassert>.
Your print method is already pretty good, congratz!
Just two nitpicks:
if you know that nothing further will be executed, return immediately, don't wait
don't use endl, it both appends an end of line AND flushes the buffer immediately, which leads to performance issues more often than not
// Prints the list, in order.
void print(Node* head) {
if (head == nullptr) {
std::cout << "empty list\n";
return;
}
for (Node* p = head; p != nullptr; p = p->next) {
std::cout << "Book ISBN: " << p->ISBN << "\n";
}
}
And finally, the modified main.
Note that I expanded the help text a bit, and provided a (clean) quit operation.
The main change, however, is dealing without input error. Dealing with output error is left as an exercise to the reader (hint: make them throw).
It would also be a good exercise to properly deal with the allocated memory.
int main() {
std::cout << "Enter one of the following operations when prompted:\n"
" - add <isbn>\n"
" - print\n"
" - quit\n";
Node* head = nullptr;
while (1) {
std::cout << "> ";
std::string op;
if (!(std::cin >> op)) {
std::cerr << "An error occurred reading the operation, sorry\n";
break;
}
if (op == "quit") {
std::cout << "See you later!\n";
break;
}
if (op == "print") {
print(head);
continue;
}
if (op == "add") {
int isbn = 0;
if (!(std::cin >> isbn)) {
std::cout << "Please provide a correct ISBN!\n";
continue;
}
Node* node = new Node();
node->ISBN = isbn;
Node* h = add(head, node);
if (h == nullptr) {
std::cout << "This ISBN was already provided!\n";
delete node;
continue;
}
head = h;
continue;
}
std::cout << "Please enter a valid operation!\n";
}
// Deal with allocated memory ;)
}
st::next is never set to NULL. This makes testing p!=NULL in print somewhat problematic.
Solution: NULL next when the node is the tail node.
I'm writing a program for a homework assignment that creates and manipulates a linked list. I am encountering an "EXC_BAD_ACCESS" error with the Node::SetData function in Node.cpp, as well as with a line in List::Add_End in List.cpp (specifically "current->SetData(data);") and a line in main.cpp for some reason (specifically "// Add_End nodes to the list"). I assume that once the Node::SetData error is fixed, these other errors will resolve themselves.
After searching through Stack Overflow and Google, I cannot determine why this error is occurring. I thought this question (New to C++, "EXC_BAD_ACCESS" error I don't understand) would help, but I'm still having issues.
What coding error(s) have I made?
main.cpp
#include <iostream>
#include <cstddef>
using namespace std;
#include "List.h"
int main()
{
// New list
List list;
Node *answer;
// Add_End nodes to the list
list.Add_End(111);
list.Print();
list.Add_End(222);
list.Print();
list.Add_End(333);
list.Print();
list.Add_End(444);
list.Print();
list.Add_End(555);
list.Print();
// Delete nodes from the list
list.Delete(444);
list.Print();
list.Delete(333);
list.Print();
list.Delete(222);
list.Print();
list.Delete(555);
list.Print();
list.Delete(111);
list.Print();
cout << "Testing Add_Front: and others" << endl;
list.Add_Front(888);
list.Print();
list.Add_Front(999);
list.Print();
list.Add_Front(49);
list.Print();
cout << "Checking find function" << endl;
answer = list.Find(888);
cout << "Value for node returned by find function call with 888 is " << answer->Data() << "." << endl;
cout << "Checking find function" << endl;
answer = list.Find(999);
cout << "Value for node returned by find function call with 888 is " << answer->Data() << "." << endl;
cout << "Checking find function" << endl;
answer = list.Find(49);
cout << "Value for node returned by find function call with 888 is " << answer->Data() << "." << endl;
cout << "Call find function with value not in list." << endl;
answer = list.Find(7);
if (answer == NULL)
{
cout << "returned null pointer since 7 not found" << endl;
}
else
{
cout << "in else of answer == NULL where Value for node returned by find function call with 7 is " << answer->Data() << "." << endl;
}
cout << "testing delete_front: " << endl;
list.Delete_Front();
list.Print();
cout << "testing delete_end: " << endl;
list.Delete_End();
list.Print();
return 0;
}
List.h
#ifndef LIST_H
#define LIST_H
#include <cstddef>
#include "Node.h"
class List
{
private:
Node* head;
public:
List();
void Add_End(int data);
void Delete(int data);
void Delete_Front();
void Add_Front(int data);
void Delete_End();
Node* Find(int data);
void Print();
};
#endif
List.cpp
#include <iostream>
#include <cstddef>
using namespace std;
#include "List.h"
List::List()
{
head = NULL;
return;
}
void List::Add_End(int data)
{
Node* current;
Node* newEnd = new Node();
for (current = head; current != NULL; current = current->Next())
{}
current->SetData(data);
current->SetNext(newEnd);
newEnd->SetData(NULL);
newEnd->SetNext(NULL);
return;
}
void List::Delete(int data) {
/*
FILL IN CODE (will do later)
*/
return;
}
void List::Delete_Front()
{
/*
FILL IN CODE (will do later)
*/
return;
}
void List::Add_Front(int data)
{
Node* newNode = new Node();
newNode->SetData(data);
newNode->SetNext(head);
head = newNode;
return;
}
void List::Delete_End()
{
if (head == NULL)
{
cout << "List has no member so cannot delete end" << endl;
return;
}
// check if one in length
if (head->Next() == NULL)
{
head = NULL;
return;
}
// 2 or greater in length
Node* current;
Node* prev;
prev = head;
for (current = head->Next(); current->Next() != NULL; current = current->Next())
{
prev = current;
}
prev->SetNext(NULL);
return;
}
Node* List::Find(int data)
{
Node* current;
for (current = head; current != NULL && current->Data() != data; current = current->Next())
{}
if(current == NULL)
{
cout << "Did not find " << data << "." << endl;
return NULL;
}
else // found
{
cout << "Found " << data << "." << endl;
return current;
}
}
void List::Print()
{
Node* current;
for (current = head; current != NULL; current = current->Next())
{
cout << current->Data() << " ";
}
cout << endl;
return;
}
Node.h
#ifndef NODE_H
#define NODE_H
class Node
{
private:
int data;
Node* next;
public:
Node();
void SetData(int aData);
void SetNext(Node* aNext);
int Data();
Node* Next();
};
#endif
Node.cpp
#include <cstddef>
#include "Node.h"
Node::Node()
{
this->SetData(NULL);
this->SetNext(NULL);
return;
}
void Node::SetData(int aData)
{
this->data = aData;
return;
}
void Node::SetNext(Node* aNext)
{
this->next = aNext;
return;
}
int Node::Data()
{
return data;
}
Node* Node::Next()
{
return next;
}
While calling current->SetData for the first time (see below) current is NULL and so you get page fault when accessing it (page fault is the error modern OSes give you if you try to access unallocated memory. Under wndows the term usually is Access violation.)
void List::Add_End(int data)
{
Node* current;
Node* newEnd = new Node();
for (current = head; current != NULL; current = current->Next())
{}
current->SetData(data);
current->SetNext(newEnd);
newEnd->SetData(NULL);
newEnd->SetNext(NULL);
return;
}
I managed to correct the code, so I'll explain what I did in case someone else encounters the same problem.
ALTERATION: Before I explain the fix, let me explain a change I made. The last node of the linked list can hold a data value itself, not just NULL (i.e., the last node's data does not need to be NULL, but its next should be NULL), so I thought this would be better. The code reflects this in every location where it matters, such as the List::Add_End(int data) function.
THE FIX: I modified the List constructor to create a head node for the list. So, the linked list will always have at least one node, even if the list is empty. I will explain how the program discerns between empty and nonempty lists later.
Here is the original constructor:
List::List()
{
head = NULL;
return;
}
Here is the new constructor:
List::List()
{
Node* headNode = new Node();
head = headNode;
return;
}
Why make this modification? As far as I can tell, I encountered the EXC_BAD_ACCESS error because the List::Add_End(int data) function tried to manipulate the linked list's head as if it were a node object, when actually it was not. (I believe this is what marom meant in his answer to this question.) This is why I altered the coding such that the list always contains a head node, even when the list is empty.
Discerning between empty and nonempty lists. I altered the Node constructor to set data to the integer -1122334455, instead of NULL like I originally did. So, if the list is empty, then head->Data() (i.e., the head node's data) is -112233455 and head->Next() (i.e., the head node's next) is NULL. The downside to this approach is that it's impossible to have a one-item list containing the integer -1122334455, but I figure this number is likely to be unneeded. As long as the list has at least two items, head->Data() can be -1122334455.
NEW CODE: The rest of the code reflects these modifications. Since I only made significant changes to List.cpp and Node.cpp, I have reproduced only them below. The other three program files are essentially unchanged. FYI, there are many redundant return's and this's that I didn't bother to delete.
List.cpp
#include <iostream>
#include <cstddef>
using namespace std;
#include "List.h"
// -1122334455 is an arbitrary integer that is likely to never be needed by the user
List::List()
{
Node* headNode = new Node();
head = headNode;
return;
}
Node* List::Add_End(int data)
{
// if list is empty (i.e., list has only head node with data == -1122334455 & next == NULL)
if (head->Data() == -1122334455 && head->Next() == NULL)
{
head->SetData(data);
return head;
}
// if list is nonempty
else
{
Node* current;
Node* newEnd = new Node();
for (current = head; current->Next() != NULL; current = current->Next())
{}
current->SetNext(newEnd);
newEnd->SetData(data);
newEnd->SetNext(NULL);
return newEnd;
}
}
void List::Delete(int data)
{
Node* prev;
Node* current;
// if list is empty
if (head->Data() == -1122334455 && head->Next() == NULL)
{
cout << "Cannot delete this datum because list is empty." << endl;
return;
}
// if list contains 1 element
if (head->Data() == data && head->Next() == NULL)
{
head->SetData(-1122334455);
return;
}
else if (head->Data() != data && head->Next() == NULL)
{
cout << "Datum not found in list." << endl;
return;
}
// if list contains 2 or more elements
prev = head;
for (current = head->Next(); current->Data() != data && current->Next() != NULL; current = current->Next())
{
prev = prev->Next();
}
if (current->Data() == data && current->Next() != NULL)
{
prev->SetNext(current->Next());
delete current;
return;
}
else if (current->Data() == data && current->Next() == NULL)
{
prev->SetNext(NULL);
delete current;
return;
}
else
{
cout << "Datum not found in list." << endl;
return;
}
}
void List::Delete_Front()
{
Node* origHead = head;
Node* newHead = head->Next();
head = newHead;
delete origHead;
return;
}
void List::Add_Front(int data)
{
// if list is empty
if (head->Data() == -1122334455 && head->Next() == NULL)
{
head->SetData(data);
return;
}
// if list is nonempty
Node* newNode = new Node();
newNode->SetData(data);
newNode->SetNext(head);
head = newNode;
return;
}
void List::Delete_End()
{
if (head->Data() == -1122334455 && head->Next() == NULL)
{
cout << "List has no member so cannot delete end" << endl;
return;
}
// check if one in length
else if (head->Data() != -1122334455 && head->Next() == NULL)
{
head->SetData(-1122334455);
return;
}
// 2 or greater in length
else
{
Node* current;
Node* prev;
prev = head;
for (current = head->Next(); current->Next() != NULL; current = current->Next())
{
prev = current;
}
prev->SetNext(NULL);
return;
}
}
Node* List::Find(int data)
{
Node* current;
for (current = head; current != NULL && current->Data() != data; current = current->Next())
{}
if (current == NULL)
{
cout << "Did not find " << data << "." << endl;
return NULL;
}
else // found
{
cout << "Found " << data << "." << endl;
return current;
}
}
void List::Print()
{
if (head->Data() == -1122334455 && head->Next() == NULL)
{
cout << "List is empty." << endl;
return;
}
Node* current;
for (current = head; current != NULL; current = current->Next())
{
cout << current->Data() << " ";
}
cout << endl;
return;
}
Node.cpp
#include <cstddef>
#include "Node.h"
Node::Node()
{
// -1122334455 is an arbitrary integer that is likely to never be needed by the user
this->SetData(-1122334455);
this->SetNext(NULL);
return;
}
void Node::SetData(int aData)
{
this->data = aData;
return;
}
void Node::SetNext(Node* aNext)
{
this->next = aNext;
return;
}
int Node::Data()
{
return this->data;
}
Node* Node::Next()
{
return this->next;
}
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;