Need help traversing a tree; Huffman Coding - c++

I have created a Huffman Tree and It appears to be correct, however I am weak when it comes to traversing data structures. I drew out the Tree on paper based on the information contained in my root tree and it appears to be well, however My code is faulty and I do not know hot to fix it.
The first 0 is persisting and, every time i take right, it seems to append a 0 after.
example:
L: 01
H: 1111
but my traversal gives me:
L: 001
H: 01010101
code Snippets
struct node
{
int symbol;
int frequency;
node* left;
node* right;
};
void Huffman::generateCode(node *tree, std::string code)
{
if(tree->left == NULL && tree->right == NULL)
{
//std::cout << "Leaf Found: " << tree->symbol << "\t" << code << std::endl;
mapCode.insert(std::pair<int, std::string>(tree->symbol,code));
}
if(tree->left != NULL)
{
code.append("0");
generateCode(tree->left, code);
}
if(tree->right != NULL)
{
code.append("1");
generateCode(tree->right, code);
}
}
UPDATE SOLVED: i figure out that the code.append(); function was messing it up. i changed it too code + "0";
void Huffman::generateCode(node *tree, std::string code)
{
if(tree->left == NULL && tree->right == NULL)
{
std::cout << "Leaf Found: " << tree->symbol << "\t" << code << std::endl;
mapCode.insert(std::pair<int, std::string>(tree->symbol,code));
}
if(tree->left != NULL)
{
generateCode(tree->left, code + "0");
}
if(tree->right != NULL)
{
generateCode(tree->right, code + "1");
}
}

you missed the elses:
void Huffman::generateCode(node *tree, std::string code)
{
if(tree->left == NULL && tree->right == NULL)
{
//std::cout << "Leaf Found: " << tree->symbol << "\t" << code << std::endl;
mapCode.insert(std::pair<int, std::string>(tree->symbol,code));
}
else if(tree->left != NULL)
{
code.append("0");
generateCode(tree->left, code);
}
else if(tree->right != NULL)
{
code.append("1");
generateCode(tree->right, code);
}
}

Related

What does if(!root){ return; } mean in c++

void printCodes(struct MinHeapNode* root, string str)
{
if (!root)
return;
if (root->data != '$')
cout << root->data << ": " << str << "\n";
printCodes(root->left, str + "0");
printCodes(root->right, str + "1");
}
if(root) is equivalent to if(root != nullptr), so if(!root) represent if(root==nullptr).
[!!= -> ==]
A precondition for almost every recursive function.
So when you receive back a nullptr root, it means that function reached to the end of the given tree.

Binary Search Tree- deleting a node causes other methods errors c++

I have a problem with deleting node from BST. I wrote a method that searches a node, that works fine, and when I'm trying to delete a leaf (an only case that I wrote so far) it causes an error (0xDDDD...) in printing methods. I assume that is because printing methods encounter some kind of null, but I have no idea how to fix that. Here is the code...
Deleting node by value method:
void deleteNodeByValue(T val)
{
cout << "\nElement to delete: " << val << " \n";
Node<T>* tmp = root;
while (tmp != NULL)
{
if (val == tmp->data)
{
cout << "Element found: " << tmp->data << " \n";
if (tmp->right_child == NULL && tmp->left_child == NULL)
{
delete tmp;
tmp = NULL;
size--;
}
break;
}
else if (val > tmp->data)
{
tmp = tmp->right_child;
}
else if (val < root->data)
{
tmp = tmp->left_child;
}
}
}
and tree print:
string to_string()
{
stringstream ss;
Node<T>* tmp = root;
queue<Node<T>*> q;
while (!q.empty() || tmp != NULL)
{
if (tmp != NULL)
{
q.push(tmp);
tmp = tmp->left_child; //debugger shows error in this place
}
else
{
tmp = q.front();
q.pop();
ss << "Data: " << tmp->data;
if (tmp->left_child != NULL)
{
ss << " Left child: " << tmp->left_child->data;
}
if (tmp->right_child != NULL)
{
ss << " Right child: " << tmp->right_child->data;
}
ss << " \n";
tmp = tmp->right_child;
}
}
return ss.str();
It also causes error in other methods like getting tree height or getting trees in order, whatever.
What should I do?
Simple, you delete the node, but the parent of that node still points to it. So you are trying to print a deleted node.
You have to remember who was the parent of the node you delete and to update it to no longer point to it.
Many ways to do it, I personally would make tmp a double pointer if I was you but since your name is newbie here is a little easier to read solution:
cout << "\nElement to delete: " << val << " \n";
Node<T>* tmp = root;
Node<T>* parent = NULL;
while (tmp != NULL)
{
if (val == tmp->data)
{
cout << "Element found: " << tmp->data << " \n";
if (tmp->right_child == NULL && tmp->left_child == NULL)
{
if (parent == NULL) root = NULL;
else {
if (parent->right_child == tmp) {
parent->right_child = NULL;
} else {
parent->left_child = NULL;
}
}
delete tmp;
size--;
}
break;
}
else if (val > tmp->data)
{
parent = tmp;
tmp = tmp->right_child;
}
else if (val < root->data)
{
parent = tmp;
tmp = tmp->left_child;
}
}
Of course you have to add the handling for the case when node is not a leaf too, but it looks like you understand this.

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;
}
}

How to fix segmentation error 11 in c++

I am currently writing a binary tree project in c++ and it is giving me some errors that I am struggling to understand. The error in question is a segmentation error that I have no idea how to fix. Below is the code from one one the files where all the functions are written. The function in particular that is giving me an issue is the last one - the print_pre_order_private function.
#include <iostream>
#include <cstdlib>
#include "BT.h"
using namespace std;
BT::BT()
{
root = NULL; //makes sure pointer isn't pointing at anything
}
BT::node* BT::create_leaf(int key)
{
node* n = new node;
n->key = key;
n->left = NULL;
n->right = NULL;
return n;
}
void BT::add_leaf(int key)
{
add_leaf_private(key, root);
}
void BT::add_leaf_private(int key, node* Ptr)
{
if(root == NULL)
{
root = create_leaf(key);
}
else if(key < Ptr->key)
{
if(Ptr->left != NULL)
{
add_leaf_private(key, Ptr->left);
}
else
{
Ptr->left = create_leaf(key);
}
}
else if(key > Ptr->key)
{
if(Ptr->right != NULL)
{
add_leaf_private(key, Ptr->right);
}
else
{
Ptr->right = create_leaf(key);
}
}
else
{
cout << "The key " << key << " has already been added to the tree\n";
}
}
void BT::print_in_order()
{
print_in_order_private(root);
}
void BT::print_in_order_private(node* Ptr)
{
if(root != NULL)
{
if(Ptr->left != NULL)
{
print_in_order_private(Ptr->left);
}
cout << Ptr->key << " ";
if(Ptr->right != NULL)
{
print_in_order_private(Ptr->right);
}
}
else
{
cout << "The tree is empty\n";
}
}
BT::node* BT::return_node(int key)
{
return return_node_private(key, root);
}
BT::node* BT::return_node_private(int key, node* Ptr)
{
if(Ptr != NULL)
{
if(Ptr->key == key)
{
return Ptr;
}
else
{
if(key < Ptr->key)
{
return return_node_private(key, Ptr->left);
}
else
{
return return_node_private(key, Ptr->right);
}
}
}
else
{
return NULL;
}
}
int BT::return_root_key()
{
if(root != NULL)
{
return root->key;
}
else
{
return -1;
}
}
void BT::print_children(int key)
{
node* Ptr = return_node(key);
if(Ptr != NULL)
{
cout << "Parent Node = " << Ptr->key << endl;
Ptr->left == NULL ?
cout << "Left child = NULL\n":
cout << "Left child = " << Ptr->left->key << endl;
Ptr->right == NULL ?
cout << "Right child = NULL\n":
cout << "Right child = " << Ptr->right->key << endl;
}
else
{
cout << "Key " << key << " is not in the tree\n";
}
}
int BT::find_smallest()
{
return find_smallest_private(root);
}
int BT::find_smallest_private(node* Ptr)
{
if(root == NULL)
{
cout << "The tree is empty\n";
return -1;
}
else
{
if(Ptr->left != NULL)
{
return find_smallest_private(Ptr->left);
}
else
{
return Ptr->key;
}
}
}
void BT::remove_node(int key)
{
remove_node_private(key, root);
}
void BT::remove_node_private(int key, node* parent)
{
if(root != NULL)
{
if(root->key == key)
{
remove_root_match();
}
else
{
if(key < parent->key && parent->left != NULL)
{
parent->left->key == key ?
remove_match(parent, parent->left, true) :
remove_node_private(key, parent->left);
}
else if(key < parent->key && parent->right != NULL)
{
parent->right->key == key ?
remove_match(parent, parent->right, true) :
remove_node_private(key, parent->right);
}
else
{
cout << "The key " << key << " was not found in the tree\n";
}
}
}
else
{
cout << "The tree is empty\n";
}
}
void BT::remove_root_match()
{
if(root != NULL)
{
node* delPtr = root;
int root_key = root->key;
int smallest_right_subtree;
//case 0 - 0 children
if(root->left == NULL && root->right == NULL)
{
root = NULL;
delete delPtr;
}
//case 1 - 1 child
else if(root->left == NULL && root->right != NULL)
{
root = root->right;
delPtr->right = NULL;
delete delPtr;
cout << "The root node with key " << root_key << " was deleted. "
<< " The new root contains key " << root->key << endl;
}
else if(root->right == NULL && root->left != NULL)
{
root = root->left;
delPtr->left = NULL;
delete delPtr;
cout << "The root node with key " << root_key << " was deleted. "
<< " The new root contains key " << root->key << endl;
}
//case 2 - 2 children
else
{
smallest_right_subtree = find_smallest_private(root->right);
remove_node_private(smallest_right_subtree, root);
root->key = smallest_right_subtree;
cout << "The rout key containing key " << root_key
<< " was overwritten with key " << root->key << endl;
}
}
else
{
cout << "Cannot remove root. Tree is empty\n";
}
}
void BT::remove_match(node* parent, node* match, bool left)
{
if(root != NULL)
{
node* delPtr;
int match_key = match->key;
int smallest_right_subtree;
//case 0 - 0 children
if(match->left == NULL && match->right == NULL)
{
delPtr = match;
left == true ? parent->left = NULL : parent->right = NULL;
delete delPtr;
cout << "The node containing key " << match_key << " was removed\n";
}
//case 1 - 1 child
else if(match->left == NULL && match->right != NULL)
{
left == true ? parent->left = match->left : parent->right = match->right;
match->left = NULL;
delPtr = match;
delete delPtr;
cout << "The node containing key " << match_key << " was removed\n";
}
//case 2 - 2 children
else
{
smallest_right_subtree = find_smallest_private(match->right);
remove_node_private(smallest_right_subtree, match);
match->key = smallest_right_subtree;
}
}
else
{
cout << "Cannot remove match. The tree is empty";
}
}
void print_pre_order()
{
print_pre_order_private(root);
}
void print_pre_order_private(node* Ptr)
{
if(root != NULL)
{
cout << Ptr->key << " ";
print_pre_order_private(Ptr->left);
print_pre_order_private(Ptr->right);
}
}
Any help in fixing this situation is greatly appreciated. Thanks in advance. :)
In print_pre_order_private(node* Ptr) function. Shouldn't this be "if(Ptr != NULL)" instead of "if(root != NULL)" ?. I think there is the crash.
Since you have designed "print_pre_order_private()" function as a recursive function you should check for the validity of "Ptr" instead of always checking for the validity of "root", since the left/right/both of the child may be NULL at the very bottom of the tree depending on your input.

Printing an expression tree

I am able to print my expression tree in inorder. But I need to be able to print it in inorder with parenthesis. for example postorder 53+ should output (5+3)
I currently have:
void printTree(struct TreeNode *tree)
{
if (tree != NULL)
{
if (isalpha(tree->info) || isdigit(tree->info))
cout << "(";
printTree( tree->left);
cout<< tree->info;
printTree(tree->right);
if (isalpha(tree->info) || isdigit(tree->info))
cout << ")";
}
}
But this gives me incorrect output. If i enter postfix expression 62/5+ it gives me (6)/(2)+(5)
:(
You need to distinguish between leaf nodes and non-leaf nodes. Only non-leaf nodes are enclosed in parantheses.
bool isLeaf(struct TreeNode* tree) {
return tree->left == 0 && tree->right == 0;
}
void printTree(struct TreeNode* tree) {
if (tree != NULL) { // this test could be omitted if the printed tree is not empty
if (isLeaf(tree)) {
cout << tree->info;
}
else {
cout << "(";
printTree(tree->left);
cout << tree->info;
printTree(tree->right);
cout << ")";
}
}
}
Try reversing the if conditions that decide whether the parentheses should be printed :
void printTree(struct TreeNode *tree)
{
if (tree != NULL)
{
if (!(isalpha(tree->info) || isdigit(tree->info)))
cout << "(";
printTree( tree->left);
cout<< tree->info;
printTree(tree->right);
if (!(isalpha(tree->info) || isdigit(tree->info)))
cout << ")";
}
}
Or probably even better :
void printTree(struct TreeNode *tree)
{
if (tree != NULL)
{
if (isoperator(tree->info))
cout << "(";
printTree( tree->left);
cout<< tree->info;
printTree(tree->right);
if (isoperator(tree->info))
cout << ")";
}
}
where isoperator is appropriately defined to distinguish operators from operands.