Why is one of my print functions deleting nodes? - c++

OK so I have a print function for my binary tree program that prints everything in Breadth-First. When I call it, it prints in the order that I would expect it to, however it also deletes all but ones of the nodes and leaves me with an empty tree.
void BST::breadth(Node *& cur_root)
{
if (cur_root != NULL) {
cout << cur_root->m_value;
if (cur_root->m_left != NULL) {
myqueue.push(cur_root->m_left);
}
if (cur_root->m_right != NULL) {
myqueue.push(cur_root->m_right);
}
if (!myqueue.empty()) {
cout << ", ";
cur_root = myqueue.front();
myqueue.pop();
breadth(cur_root);
} else {
cout << "}" << endl;
}
}
}
I assumed that popping the node off of myqueue might have been the problem, yet I don't have this problem when I use my normal print function (In-Order Traversal).
void BST::print(Node *& cur_root)
{
if (cur_root != NULL) {
print(cur_root->m_left);
myqueue.push(cur_root);
print(cur_root->m_right);
}
int sizecompare = myqueue.size();
if (size() == sizecompare) {
while (!myqueue.empty()) {
cout << myqueue.front()->m_value;
myqueue.pop();
if (!myqueue.empty()) {
cout << ", ";
}
}
cout << "}" << endl;
}
}
They both use the same queue of nodes, so I don't understand why they would behave differently when popped. So is the pop function the culprit? If so, why does it only happen on one function? Is there a way I can work around it so my nodes aren't destroyed?

Because you are passing cur_root by reference instead of by value. When your breadth function returns, your cur_root is pointing to something else (the end of the tree).
You can also avoid the recursion:
void BST::breadth(Node* root)
{
std::queue<Node*> myqueue;
myqueue.push_back(root);
bool first = true;
cout << "{";
while (myqueue.empty() == false) {
cout << (first ? "" : ",");
first = false;
Node* current = myqueue.front();
myqueue.pop();
cout << current->m_value;
if (current->left) {
myqueue.push(current->left);
}
if (current->right) {
myqueue.push(current->right);
}
}
cout << "}" << endl;
}

void BST::breadth(Node *& cur_root)
Takes in a reference to a pointer.
cur_root = myqueue.front();
Changes it to be one of the child nodes. You just overwrote it.

Related

Print Level Wise Binary Tree in C++

The output is giving - Runtime Error (SIGSEGV). What could be the problem?
QUestion:
Given a binary tree, print the tree in level wise order.
For printing a node with data N, you need to follow the exact format -
N:L:x,R:y
wherer, N is data of any node present in the binary tree. x and y are the values of left and right child of node N. Print -1. if any child is null.
There is no space in between.
You need to print all nodes in the level order form in different lines.
Input format :
Elements in level order form (separated by space)
(If any node does not have left or right child, take -1 in its place)
Sample Input :
8 3 10 1 6 -1 14 -1 -1 4 7 13 -1 -1 -1 -1 -1 -1 -1
Sample Output :
8:L:3,R:10 3:L:1,R:6 10:L:-1,R:14 1:L:-1,R:-1 6:L:4,R:7 14:L:13,R:-1
4:L:-1,R:-1 7:L:-1,R:-1 13:L:-1,R:-1
Here is the code:
// Following is the Binary Tree node structure
/**************
class BinaryTreeNode {
public :
T data;
BinaryTreeNode<T> *left;
BinaryTreeNode<T> *right;
BinaryTreeNode(T data) {
this -> data = data;
left = NULL;
right = NULL;
}
};
***************/
void printLevelWise(BinaryTreeNode<int> *root) {
if(root == NULL){
return;
}
cout << root->data << ":";
queue<BinaryTreeNode<int>*> pendingNodes;
pendingNodes.push(root);
while(pendingNodes.size() != NULL){
BinaryTreeNode<int>* front = pendingNodes.front();
pendingNodes.pop();
if(front->left->data != -1){
cout << "L:" << front->left->data << ",";
pendingNodes.push(front->left);
}
else if(front->left->data == -1){
cout << "L:" << "-1" << ",";
}
if(front->right->data != -1){
cout << "R:" << front->right->data;
pendingNodes.push(front->right);
}
else if(front->left->data == -1){
cout << "R:" << "-1";
}
cout << endl;
}
/* Don't write main().
* Don't read input, it is passed as function argument.
* Print output and don't return it.
* Taking input is handled automatically.
*/
}
if(front->left->data != -1)
when your subtree not contain left node and you are checking left->data!=-1
thats why you are getting Runtime Error (SIGSEGV)
Use this code
/**************
class BinaryTreeNode {
public :
T data;
BinaryTreeNode<T> *left;
BinaryTreeNode<T> *right;
BinaryTreeNode(T data) {
this -> data = data;
left = NULL;
right = NULL;
}
};
***************/
void printLevelWise(BinaryTreeNode<int> *root) {
if(root == NULL){
return;
}
queue<BinaryTreeNode<int>*> pendingNodes;
pendingNodes.push(root);
while(pendingNodes.size() != NULL){
BinaryTreeNode<int>* front = pendingNodes.front();
pendingNodes.pop();
cout << front->data << ":";
if(front->left){
if(front->left->data != -1){
cout << "L:" << front->left->data << ",";
pendingNodes.push(front->left);
}
else{
cout << "L:" << "-1" << ",";
}
}
if(front->right){
if(front->right->data != -1){
cout << "R:" << front->right->data;
pendingNodes.push(front->right);
}
else{
cout << "R:" << "-1";
}
}
}
/* Don't write main().
* Don't read input, it is passed as function argument.
* Print output and don't return it.
* Taking input is handled automatically.
*/
}
As the description says, you should print "-1" if a child is null.
It does not say that you should print "-1" if the child's data is -1.
This would be the same as printing the data, so it would not be described as a special case.
(It is very important to read problem descriptions thoroughly. I think you're confusing this with the program's input format, which has -1 to indicate the absence of a child node, but that's not the input to your function.)
You need
if(front->left != nullptr) {
cout << "L:" << front->left->data << ",";
pendingNodes.push(front->left);
}
else {
cout << "L:" << "-1" << ",";
}
(You're also going to need to adjust how you print commas, but that's a different problem.)
void printLevelWise(BinaryTreeNode<int> *root)
{
if (root == NULL)
{
return;
}
queue<BinaryTreeNode<int> *> pendingNodes;
pendingNodes.push(root);
while (pendingNodes.size() != NULL)
{
BinaryTreeNode<int> *front = pendingNodes.front();
pendingNodes.pop();
cout << front->data << ":";
if (front->left)
{
if (front->left->data != -1)
{
cout << "L:" << front->left->data << ",";
pendingNodes.push(front->left);
}
}
else
{
cout << "L:"<< "-1"<< ",";
}
if (front->right)
{
if (front->right->data != -1)
{
cout << "R:" << front->right->data;
pendingNodes.push(front->right);
}
}
else
{
cout << "R:"<< "-1";
}
cout<<endl;
}
}

Displaying null children of binary tree in output

I have a method that prints the levels of a binary tree:
template<class BTNode>
void breadthfirstByLevel(BTNode* node_ptr) {
if (node_ptr == NULL)
{
return;
}
queue<BTNode *> q1;
queue<BTNode *> q2;
q1.push(node_ptr);
while (!q1.empty() || !q2.empty()) {
while (!q1.empty())
{
node_ptr = q1.front();
q1.pop();
cout << node_ptr->data() << " ";
if (node_ptr->left() != NULL)
{
q2.push(node_ptr->left());
}
if (node_ptr->right() != NULL)
{
q2.push(node_ptr->right());
}
}
cout << endl;
while (!q2.empty())
{
node_ptr = q2.front();
q2.pop();
cout << node_ptr->data() << " ";
if (node_ptr->left() != NULL)
{
q1.push(node_ptr->left());
}
if (node_ptr->right() != NULL)
{
q1.push(node_ptr->right());
}
}
cout << endl;
}
}
I check for the children of the current node to be null and push them into the queue. How can I display "NULL" in the level output instead of just skipping it and printing nothing?
You take the pointer of the next node from the queue to print data. If this node has children (i.e. pointer to child not null), you put them in the queue. This means that in the queue you'll never have a nullptr.
You can solve this using a variant of the algorithm: you could put nullptr in the queue in absence of child. But you then have to make sure when you get pointers from the queue not to dereference them.
...
while (!q1.empty() || !q2.empty()) {
while (!q1.empty())
{
node_ptr = q1.front();
q1.pop();
if (node_ptr==nullptr) { // if nullptr was on queue
cout << "<NULL> "; // tell it
}
else { // otherwise handle data and queue its children
cout << node_ptr->data() << " ";
q2.push(node_ptr->left()); // push even if it's nullptr
q2.push(node_ptr->right()); // " "
}
}
... // then same for q2
}

Bug in AVL tree code, data structures c++

I am really trying to figure out the bug in my code I wrote for AVL tree but there seems to be a bug in it.
It calls the rotation functions but when it finishes rotation there are several problem:
root doesn't change
only root value is displayed when in-order traversal is done, other values seem to disappear
I have been trying to fix this bug since 2-3 days but cant seem to solve it.
Would love some help from you guys. I will be attaching the code with this.
/*
insertion
rotations all DONE
level order DONE
deletion
*/
#include <iostream>
#include <queue>
using namespace std;
struct node
{
int data;
int height;
node *left;
node *right;
node()
{
height = 0;
left = right = NULL;
}
};
class AVL
{
public:
node *root;
AVL()
{
root = NULL;
}
// search function
bool search(int num)
{
node *nodePtr = root;
if (root->data == num)
{
cout << "FOUND " << endl;
return true;
}
else
{
while (nodePtr != NULL)
{
if (nodePtr->data < num)
{
nodePtr = nodePtr->right;
}
else if (nodePtr->data > num)
{
nodePtr = nodePtr->left;
}
else
{
cout << "FOUND " << endl;
return true;
}
}
cout << "NOT FOUND " << endl;
return false;
}
}
// inorder
void inorder()
{
inorder(root);
}
// postorder
void postorder()
{
postorder(root);
}
// preorder
void preorder()
{
preorder(root);
}
// inorder utility function
void inorder(node *&nodePtr)
{
if (nodePtr)
{
inorder(nodePtr->left);
cout << nodePtr->data << ", ";
inorder(nodePtr->right);
}
}
// preorder utility function
void preorder(node *&nodePtr)
{
if (nodePtr)
{
cout << nodePtr->data << ", ";
preorder(nodePtr->left);
preorder(nodePtr->right);
}
}
// postorder utility function
void postorder(node *&nodePtr)
{
if (nodePtr)
{
postorder(nodePtr->left);
postorder(nodePtr->right);
cout << nodePtr->data << ", ";
}
}
// returns the number of nodes in the tree
int size(node *&nodePtr)
{
if (!nodePtr)
{
return 0;
}
else
{
return (size(nodePtr->left) + size(nodePtr->right)) + 1;
}
}
// function to check if tree is empty or not
bool isempty()
{
if (root == NULL)
{
return true;
}
else
{
return false;
}
}
// max function to calculate height and also the balance factor
int maximum(int x, int y)
{
if (x>y)
{
return x;
}
else
{
return y;
}
}
// returns the level of the tree
int returnHeight(node *&nodePtr)
{
if (nodePtr == NULL)
{
return 0;
}
else
{
return nodePtr->height;
}
}
// assigning the height to the node
void assignHeightToNode(node *&nodePtr)
{
int left = returnHeight(nodePtr->left);
int right = returnHeight(nodePtr->right);
nodePtr->height = maximum(left, right) + 1;
}
// single left rotate
node *singleLeftRotate(node *&nodePtr)
{
// if (nodePtr==NULL)
// {
// return;
// }
node * b = nodePtr->right;
nodePtr->right = b->left;
b->left = nodePtr;
return b;
}
// single right rotate
node *singleRightRotate(node *&nodePtr)
{
// if (nodePtr==NULL)
// {
// return ;
// }
node * b = nodePtr->left;
nodePtr->left = b->right;
b->right = nodePtr;
assignHeightToNode(nodePtr);
assignHeightToNode(b);
return b;
}
// double left rotate
node *doubleLeft(node *&nodePtr)
{
nodePtr->right = singleRightRotate(nodePtr->right);
return singleLeftRotate(nodePtr);
}
// double right rotate
node *doubleRight(node *&nodePtr)
{
nodePtr->left = singleLeftRotate(nodePtr->left);
return singleRightRotate(nodePtr);
}
// insert function
void insert1(int x)
{
cout << "NOW INSERTING " << x << endl;
insert2(x, root);
}
// insert utility function
void insert2(int &x, node *&nodePtr)
{
if (nodePtr == NULL)
{
node *newNode = new node;
newNode->data = x;
newNode->height = 0;
nodePtr = newNode;
checkRotations(nodePtr, x);
return;
}
else
{
if (x < nodePtr->data)
{
cout << endl << "GOING LEFT " << endl;
insert2(x, nodePtr->left);
}
else if (x > nodePtr->data)
{
cout << endl << "GOING RIGHT " << endl;
insert2(x, nodePtr->right);
}
else if (nodePtr->data == x)
{
cout << "DUPLICATE VALUES NOT ALLOWED " << endl;
return;
}
}
checkRotations(nodePtr, x);
}
// checking if rotations needed
void checkRotations(node *&nodePtr, int &x)
{
assignHeightToNode(nodePtr);
cout << endl << endl << "HEIGHT OF " << nodePtr->data << " IS " << nodePtr->height << endl;
int bf = returnHeight(nodePtr->left) - returnHeight(nodePtr->right);
cout << endl << endl << "BALANCE FACTOR AT NODE " << nodePtr->data << " IS " << bf << endl;
if (bf < -1 || bf > 1)
{
cout << endl << endl << "ROTATION IS HAPPEENING " << endl << endl;
if (x > nodePtr->data)
{
singleLeftRotate(nodePtr);
cout << endl << "ROTATION DONE SINGLE LEFT " << endl;
return;
}
else if (x < nodePtr->data)
{
singleRightRotate(nodePtr);
cout << endl << "ROTATION DONE SINGLE RIGHT " << endl;
return;
}
else if (x < root->data && x > root->left->data)
{
doubleRight(nodePtr);
cout << endl << "ROTATION DONE DOUBLE LEFT " << endl;
return;
}
else if (x > root->data && x < root->right->data)
{
doubleLeft(nodePtr);
cout << endl << "ROTATION DONE DOUBLE LEFT " << endl;
return;
}
}
}
// level order display code
void levelOrderDisplay()
{
levelOrderDisplay2(root);
}
// level order display utility function
void levelOrderDisplay2(node *&nodePtr)
{
if (nodePtr == NULL)
{
cout << "THE TREE IS EMPTY" << endl;
return;
}
queue <node *> displayer;
displayer.push(nodePtr);
while (!displayer.empty())
{
node *currentNode = displayer.front();
cout << currentNode->data << ", ";
if (currentNode->left != NULL)
{
displayer.push(currentNode->left);
}
else if (currentNode->right != NULL)
{
displayer.push(currentNode->right);
}
displayer.pop();
}
}
void rootD()
{
cout << "root is " << root->data << endl;
}
};
int main()
{
AVL tree;
tree.insert1(3);
tree.insert1(2);
tree.insert1(1);
tree.insert1(4);
tree.insert1(5);
tree.insert1(6);
tree.insert1(7);
tree.inorder();
// tree.rootD();
// tree.levelOrderDisplay();
// tree.rootD();
return 0;
}
I suggest you that do not pass node pointer by reference where your code does not change pointer value such as print. Try this... I completed my avl tree code just 2 3 day before and i have similar problem, when i debug my program i came to know that somehow in print function my pointer value is changed because i passed it by reference..... So.. Try this and see if work or not.... Hope this might help you.
Really late answer, but this is what you had to do. You should set the node passed in the function equal to the temporary node made in the function. In coding language, nodePtr=b should have been the last line of the single rotate functions.
Hope this helps :)

Access violation for a specific function

I have many functions in my CustomerList.cpp file, the only one of which that doesn't work is shown below (and the break point is marked with a comment). NOTE: Store class is correct, and m_pHead is a CustomerList private variable (but that shouldn't matter).
bool CustomerList::removeStore(int ID)
{
Store *back, *temp;
if(m_pHead = NULL)
{
cout << "\nError! Store " << ID << " not found in the List!\n";
system("pause");
return false; // nothing to delete
}
// Search for the item to delete
back = NULL;
temp = m_pHead;
while((temp != NULL) && (temp->getStoreID() != ID))
{
back = temp;
temp = temp->m_pNext;
}
if(back == NULL) // Delete the first item in the list
{
m_pHead = temp->m_pNext; // THE FUNCTION BREAKS HERE
delete temp;
cout << "\nSuccess! Store " << ID << " added to List!\n";
system("pause");
return true;
}
else if(temp != NULL) // Delete from middle or end of list
{
back->m_pNext = temp->m_pNext;
delete temp;
cout << "\nSuccess! Store " << ID << " added to List!\n";
system("pause");
return true;
}
else
{
cout << "\nError! Store " << ID << " not found in the List!\n";
system("pause");
return false; // Didn't find the item to delete
}
}
Every time I make a call to this function, it breaks, even if the ID of the Store is not on the list (it shouldn't make it that far in the function).
Here is an example of a call:
// Creating a new Customer List
CustomerList *newList = new CustomerList();
newList->removeStore(3);
What in the world am I doing wrong?
There are some logic errors in your code. Most notably, this line;
if(m_pHead = NULL)
Is assigning NULL to m_pHead before then comparing it. Thus, temp is NULL, and back remains NULL, which is why your code reaches the spot you commented and crashes.
You need to use the == comparison operator, not the = assignment operator (your compiler should have warned you about that):
if(m_pHead == NULL)
Or safer:
if(!m_pHead)
Now, with that said, you can simplify the rest of the code to the following:
bool CustomerList::removeStore(int ID)
{
Store *temp, *previous;
// Search for the item to delete
previous = NULL;
temp = m_pHead;
while (temp != NULL)
{
if (temp->getStoreID() == ID)
{
if (m_pHead == temp)
{
// Deleting the first item in the list
m_pHead = temp->m_pNext;
}
if (previous != NULL)
{
// Deleting from middle or end of list
previous->m_pNext = temp->m_pNext;
}
delete temp;
cout << "\nSuccess! Store " << ID << " removed from List!\n";
system("pause");
return true;
}
previous = temp;
temp = temp->m_pNext;
}
cout << "\nError! Store " << ID << " not found in the List!\n";
system("pause");
return false; // nothing to delete
}
Or, if you use a standard C++ container, such as std::list, instead of making your own manual linked-list, you can do this instead:
struct isStoreID
{
int m_id;
isStoreID(int id) : m_id(id) {}
bool operator()(const Store &store) { return (store.getStoreID() == m_id); }
};
bool CustomerList::removeStore(int ID)
{
// Search for the item to delete
// where m_list is a std::list<Store>...
std::list<Store>::iterator iter = std::find_if(m_list.begin(), m_list.end(), isStoreID(ID));
bool bWasFound = (iter != m_list.end());
if (bWasFound)
{
m_list.erase(iter);
cout << "\nSuccess! Store " << ID << " removed from List!\n";
}
else
cout << "\nError! Store " << ID << " not found in the List!\n";
system("pause");
return bWasFound;
}

C++ linked list/node templates pointer not staying NULL after method return

Having a problem where 2 pointers are passed to a method and right before the method returns I confirm with an if statement that the first is NULL, then the method returns and control goes back to main, I check this pointer again and it != NULL.
This happens in a while loop as I'm trying to iterate through a linked list so it ends up being an infinite loop (so I made the cin >> pause to check outputs before it goes crazy).
Inside a switch on a menu input in main I have:
case 'D':
{
cout.setf(ios::left);
cout << setw(20) << "Last Name" << setw(15) << "First Name"
<< setw(10) << "Priority" << setw(10) << "Arrival Time" << endl;
NodeType<PatientType> *printer;
PatientType *patientToPrint = new PatientType();
ER.startIterate(printer, patientToPrint);
while (printer != NULL) {
PatientType::printPatient(*patientToPrint);
ER.iterate(printer, patientToPrint);
if (printer != NULL) {
cout << "printer != NULL" << endl;
} else {
cout << "printer == NULL" << endl;
}
cout << "PAST ITERATE" << endl;
int pause;
cin >> pause;
}
cout << "OUT OF LOOP";
delete printer;
delete patientToPrint;
break;
}
Where NodeType is a template class (so is LinkedListType, which is ER's type)
The startIterate function being called (in LinkedListType file) is:
template<class ItemType>
void LinkedListType<ItemType>::startIterate(NodeType<ItemType> *item, ItemType *itemToPrint) {
if (head != NULL) {
item = head;
*itemToPrint = head->data;
} else {
item = NULL;
itemToPrint = NULL;
}
}
Where head is the head of the linked list (a private pointer to a NodeType)
Then the iterate function (in LinkedListType file also) is:
template<class ItemType>
void LinkedListType<ItemType>::iterate(NodeType<ItemType> *item, ItemType *itemToPrint) {
NodeType<ItemType> *peek = item->next;
if (item->next == NULL) {
std::cout << "item->next == NULL" << std::endl;
}
if (peek != NULL) {
std::cout << "peek != NULL" << std::endl;
item = item->next;
*itemToPrint = item->data;
} else {
std::cout << "peek == NULL" << std::endl;
item = NULL;
itemToPrint = NULL;
if (item == NULL) {
std::cout << "item == NULL" << std::endl;
}
}
}
After you add a couple nodes to the list and input 'D' (print list) the output works at first, printing out the head node's information, and then reads:
item->next == NULL
peek == NULL
item == NULL
printer != NULL
PAST ITERATE
Which doesn't seem to make sense, "printer" in main is the same as "item" in iterate, the output shows that upon leaving iterate it is NULL, and when arriving in main immediately after, it is not NULL.
After inputting an int for the pause variable, it keeps looping through continuously. What's more is it keeps printing out the head node's information each time too, which I also set to NULL at the end of iterate!
void LinkedListType<ItemType>::iterate(NodeType<ItemType> *& item, ItemType *itemToPrint)
See here:
Reason to Pass a Pointer by Reference in C++?