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