Building a tree from preorder in C++ - c++

I am working on a compression/decompression assignment. I'm trying to write a C++ method to build a tree using the following preorder traversal from the header of my compressed file:
001c1b01a01e1d
0 represents an internal node while 1 represents a leaf. Every time I create a node, I set the code of that node to either 0 or 1, because I will be using another method to decode the tree and it must know how to traverse down different sides by using these codes. Whenever I reach a 1 in the preorder traversal string, I set the node's "symbol" field to the following character in the preorder string. I can't get it to work though. Can anyone help? Here is my code ("bitsToRead" just represents the length of the preorder string so the method knows when to stop) Thanks!
void HCTree::buildFromHeader(ifstream& in, HCNode* n, int codeToUse) {
if( bitsToRead > 0) {
char c = in.get();
bitsToRead--;
if(c == '0') {
n = new HCNode(0, 0, 0, 0, 0, codeToUse);
if(rootSet == 0) {
root = n;
rootSet = true;
}
HCNode* left;
n->c0 = left;
HCNode* right;
n->c1 = right;
buildFromHeader(in, left, 0);
buildFromHeader(in, right, 1);
}
else {
byte symbol = in.get();
n = new HCNode(0, symbol, 0, 0, 0, codeToUse);
bitsToRead--;
n->c0 = n->c1 = NULL;
}
}
}

It seems changing
void HCTree::buildFromHeader(ifstream& in, HCNode* n, int codeToUse) {
to
void HCTree::buildFromHeader(ifstream& in, HCNode* &n, int codeToUse) {
will do the work.
Plus the rootSet logic can be omitted. You just call
buildFromHeader(in, root, codeToUse)
from the caller.
EDIT:
I misread your code in the first place. n = new HCNode(0, symbol, 0, 0, 0, codeToUse); is the code made me suggests to use a reference. Because what you want to do here is the changing the pointer passed from the leaf's ancestor (the n->c0 = left and n->c1 = right stuff). To make the whold thing work, in addition to the change above, change
HCNode* left;
n->c0 = left;
HCNode* right;
n->c1 = right;
buildFromHeader(in, left, 0);
buildFromHeader(in, right, 1);
to
buildFromHeader(in, n->c0, 0);
buildFromHeader(in, n->c1, 0);
This will let the callee to assign values transparently to pointers inside struct using references.

Related

Binary Tree level order insertion c++

I want to insert in the tree but not using any other data structures like queue. I want to insert in level order and no matter what I code, it doesn't. Also I couldn't find any code without queues or things like that.
Here is my attempt;
void insert(int x) {
if (root == NULL) {
root = new node(x, NULL, NULL);
return;
}
node *temp = root;
node *prev = root;
while (temp != NULL) {
if (temp->left != NULL) {
prev = temp;
temp = temp->left;
} else if (temp->right != NULL) {
prev = temp;
temp = temp->right;
}
}
if (temp->left == NULL)
prev->left = new node(x, NULL, NULL);
else if (temp->right == NULL)
prev->right = new node(x, NULL, NULL);
}
I don't have a link for recursive insertion but it should work like this:
bool recursion(node * current_node, node * to_insert, int &max_depth, int cur_depth) {
if(max_depth < cur_depth) {
max_depth = cur_depth;
}
for (auto & current_child : {current_node->left, current_node->right})
if(current_child == NULL) {
if( max_depth > cur_depth ) {
current_child -> left = to_insert;
return true;
}
} else {
if(recursion(current_child, to_insert, max_depth, cur_depth + 1)) {
return true;
}
}
return false;
}
This does depth-first-search (not breadth-first, I was mistaken above, they are very similar in trees) from left to right. So we will first find the left-most leaf, then the one right next to it and so on. We will always track how deep we are in the tree. If at one point we find a node on the second deepest layer that hasn't got a child, it will add the node we want to insert at this point and recurse up the tree. Due to the order in which we traverse the tree, this will find the left most open spot, so exactly what you want.
This method can return false if the submost layer of the tree is full. Then we have to go down to the left-most leaf and insert the node at its left child. One can also save this leaf somehow when we first find it, but that seemed more complicate to me then just searching it again (this can be done without problem in a for-loop).
You can replace the recursive method by an iteration with a stack (there are many sources on the internet explaining how to make a recursive depth-first-search to a iterative one).
I don't really like the in-out-parameter max_depth but it was the easiest to do this.

Don't understand why I need a return on the last lines

I'm solving a problem about figuring out the minimum path to a leaf in a tree. I'm using BFS in C++ with a queue that stores a node and the current depth.
I traverse the tree in BFS adding nodes to my queue as I go along. As soon as I reach my first leaf I exit my cycle.
I don't understand why I need to add the return 0; line at the end of the program (commented on the code).
If I remove that line I get an error saying that the function got to the end without a return.
In which case will I need it?
class TreeDepth{
TreeNode* node;
int depth;
public:
TreeDepth(int depth, TreeNode* node): depth(depth), node(node) {}
TreeNode* getNode() {return node;}
int getDepth() {return depth;}
};
class Solution {
public:
int minDepth(TreeNode* root) {
if(!root)
return 0;
else
{
std::queue<TreeDepth> depthQ;
TreeDepth nodeDepth(1,root);
depthQ.push(nodeDepth);
while(!depthQ.empty())
{
TreeDepth currentNode = depthQ.front();
depthQ.pop();
if(!currentNode.getNode()->left && !currentNode.getNode()->right)
return currentNode.getDepth();
else
{
if(currentNode.getNode()->left)
{
TreeDepth leftNodeDepth(currentNode.getDepth() + 1, currentNode.getNode()->left);
depthQ.push(leftNodeDepth);
}
if(currentNode.getNode()->right)
{
TreeDepth rightNodeDepth(currentNode.getDepth() + 1, currentNode.getNode()->right);
depthQ.push(rightNodeDepth);
}
}
}
}
return 0; // why do I need this line?
}
};
Because you have paths in the function that exit but don't return a value. For instance, if depthQ IS empty, your code would exit without returning anything (but for that final 'return 0'). And you've declared your function to return an int. So all code paths must return some int.

Find the lowest leaf in a binary tree

i'm trying to compare all leafs to return the lowest value of a tree, I don't have main function just a script to insert values so unfortunately I can't debug it.
tpNoArvore * findLowest(tpNoArvore * pNo){
tpNoArvore * left;
tpNoArvore * right;
tpNoArvore * res;
if (!pNo) return NULL; /* if */
left = findLowest(pNo->pNoL);
right = findLowest(pNo->pNoR);
if(isLeaf(pNo))
return pNo;
} /* if */
if(!left){
return right;
} /* if */
if(!right){
return left;
} /* if */
return (left->Valor < right->Valor) ? left : right ;
}
So, basically what i'm trying to achieve here is to compare the two sides of each node to find the lowest.
It seems strange that your code returns a pointer. I would expect something like:
// Assume valor is int
int findLowest(tpNoArvore * pNo){
if (!pNo) exit(1); /* fatal error */
// If this is a leaf just return its value
if(isLeaf(pNo)) return pNo->Valor;
// Not a leaf
// Find the lowest value in left part of tree
int leftValor = findLowest(pNo->pNoL);
// Find the lowest value in right part of tree
int rightValor = findLowest(pNo->pNoR);
// Return the lowest of leftValue ans rightValue
return (leftValor < rightValor) ? leftValor : rightValor ;
}
But maybe I have misundetstood your question.

Some binary tree based operations

Hi I am trying to print the non-leaf(Internal) nodes in a binary search tree . But I am not getting the desired output . Kindly rectify my error or suggest me some better algorithm .
Here is my code .
void noleaf(struct node *here)
{
if((temp -> left != NULL) || (temp -> right != NULL))
{
printf("%d" , temp -> data) ;
if(temp -> left != NULL)
{
noleaf(temp -> left) ;
}
}
noleaf(temp -> right) ;
return 0 ;
}
Another function asks me to print the mirror image of the tree . Here I used .
struct node *Mirror(struct node *t)
{
if(t == NULL)
{
return 0 ;
}
else
{
nn = (struct node *)malloc(sizeof(struct node)) ;
nn -> data = t -> data ;
nn -> left = Mirror(t -> right);
nn -> right = Mirror(t -> left) ;
return nn ;
}
}
I am new to binary trees . Kindly help .
Your logic looks like this:
If the node has at least one child, print its data, and then
if the node has a left child, recurse into that
Then, recurse into the right child, regardless of whether it exists.
I think you'll agree that printing only nodes that have at least one child, and treating one child differently than the other, is unfair.
Recursion on binary trees usually take one of the following forms:
If it is a leaf, do your leaf processing (common for all cases)
Otherwise, either
do your internal node processing and then recurse into the subtrees (preorder), or
recurse into the subtrees and then do your internal node processing (postorder), or
recurse into the left subtree, then do your internal node processing, then recurse into the right subtree (inorder).
So a preorder traversal version of noleaf might be
void noleaf(struct node *here)
{
if (here == NULL)
{
// Do nothing
}
else
{
printf("%d", here->data);
noleaf(here->left);
noleaf(here->right);
}
}
or, simplified
void noleaf(struct node *here)
{
if (here)
{
printf("%d", here->data);
noleaf(here->left);
noleaf(here->right);
}
}
Is it really necessary to distinguish non-leaf nodes when printing the tree? I have re-sequenced your instructions (and omitted a return value - your compiler should have warned you about that).
void printree(struct node *here)
{
if (here != NULL)
{
printree (here->left);
printf("%d\n", here -> data) ;
printree (here->right);
}
}
For the noleaf function you have to check if here is not NULL (if it's NULL here->left or here->right will cause a segmentation fault or an error), then you have to check if here have sons, if it does have at least one then we aren't in a leaf, if we are then we print the content of the node.
void noleaf(struct node * here) {
if (here)
if (here->left || tree->right) {
printf("%d\n",here->data);
noleaf(here->left);
noleaf(here->right);
}
}
Note: One thing that I didn't understand was why you were using temp and not here.

Recursive binary tree function

I am trying to insert items from my array into my tree. My function works fine and creates nodes all the way down to the leaf node on the left hand side of my tree. The problem is when it is supposed to return recursively when detecting a leaf node to the higher level, it just stops building the tree completely. Here is the code:
void WLD::treeInsert(BSP_Node *tree_root, int node_number)
{
if ( tree_root == NULL )
{
tree_root = new BSP_Node();
tree_root->node_number = node_number;
tree_root->normalX = bsp_array[node_number].normal[0];
tree_root->normalY = bsp_array[node_number].normal[1];
tree_root->normalZ = bsp_array[node_number].normal[2];
tree_root->splitdistance = bsp_array[node_number].splitdistance;;
tree_root->region = bsp_array[node_number].region;
tree_root->left = bsp_array[node_number].left; //because the array starts at index 0
tree_root->right = bsp_array[node_number].right; //because the array starts at index 0
tree_root->left_node = NULL;
tree_root->right_node = NULL;
errorLog.OutputSuccess("Inserting new node: %i", node_number);
errorLog.OutputSuccess("Left node index: %i", bsp_array[node_number].left);
errorLog.OutputSuccess("Right node index: %i", bsp_array[node_number].right);
node_number++;
// Check for leaf nodes
if(tree_root->region != 0)
{
errorLog.OutputSuccess("This is a leaf node! Returning!");
return;
}
}
if ( tree_root->left > 0)
{
//tree_root->left_node = new BSP_Node();
errorLog.OutputSuccess("Left node not NULL, inserting it!");
treeInsert( tree_root->left_node, tree_root->left );
}
else if (tree_root->right > 0)
{
//tree_root->right_node = new BSP_Node();
errorLog.OutputSuccess("Right node not NULL, inserting it!");
treeInsert( tree_root->right_node = NULL, tree_root->right );
}
}
As you can see, when it detects a leaf node, it is supposed to return to the calling function (this function but on a level closer to the node. Does anyone have any suggestions?
if ( tree_root->left > 0) {
// implementation
}
else if (tree_root->right > 0) {
// implementation
}
Shouldn't this be two separate if statements, rather than if/else? Otherwise it only does one or the other sides, but not both.