Binary Tree numLeaf algorithm not working - c++

I'm writing a program to try and get the number of leaves in a binary tree. What I did was I checked if the current ptr was a leaf, and if not, to keeps going to the next subtree. However, when I run it, it keeps returning 2. What am I doing wrong?
I didn't include the source code because its relatively standard (has a rLink, lLink, etc.). There are no errors when I run this:
template <class elemType>
long int bSearchTreeType<elemType>::getLeaves(nodeType<elemType> * current, long int count) const {
if(current->rLink == NULL && current->lLink == NULL) {
count += 1;
return count;
}
if(current->rLink!=NULL) {
getLeaves(current->rLink);
}
if(current->lLink!=NULL) {
getLeaves(current->lLink);
}
}
template <class elemType>
long int bSearchTreeType<elemType>::leaves() const {
if(this->root!=NULL) {
return this->getLeaves(this->root);
}
}
Edit: I declared the function with count = 1 in the parameter list. Thats why I'm able to to that.

I find a few issues.
1) You are calling return this->getLeaves(this->root); but there is no method with that method signature in the code sample you have here.
bSearchTreeType<elemType>::getLeaves(nodeType<elemType> * current, long int count)
2) Your code doesn't handle cases where the current can be null i.e) for tree's like
2
/
1
3) You are not returning anything after traversing the left and the right sub tree.
You could write something like this
template <class elemType>
long int bSearchTreeType<elemType>::getLeaves(nodeType<elemType> * current)
{
if(current == NULL)
return 0;
if(current->rLink == NULL && current->lLink == NULL)
return 1;
int leftSubTree = getLeaves(current->lLink);
int rightSubTree = getLeaves(current->rLink);
return leftSubTree + rightSubTree;
}

Related

Finding the height of a BST without returning anything from the function

I am trying to learn various data structures, and I am currently learning about trees, namely binary search trees. I have gotten most every function down, with the exception of the get height function. I found quite a lot of pseudo code on how to write this recursively, and returning the recursive path to find the height. This is what I came up with:
int getHeight(struct node* node)
{
if (node == nullptr)
return 0;
else
{
int leftDepth = getHeight(node->left);
int rightDepth = getHeight(node->right);
if (leftDepth > rightDepth)
return(leftDepth+1);
else return(rightDepth+1);
}
}
This is fine, but I wanted to stay consistent with how I wrote out my other functions. The other functions are templates, that each have a public wrapper function that is called in the driver. Then, this wrapper calls the private function that actually preforms the action that is intended. So, what I have for the get height is this:
template <typename T>
int binarySearch<T>::getHeight()
{
int height = 0;
getHeight(rootNode, height, 0);
return height;
}
template <typename T>
void binarySearch<T>::getHeight(Node *node, int &max, int layer)
{
int tempRight = 0;
int tempLeft = 0;
if (node == nullptr)
{
tempRight = -1;
tempLeft = -1;
max--;
}
else
{
if (node->left != nullptr)
{
tempLeft = 1;
getHeight(node->left, max, layer);
}
if (node->right != nullptr)
{
tempRight = 1;
getHeight(node->right, max, layer);
}
}
if (tempLeft > tempRight)
{
max++;
}
else
{
max++;
}
}
I intended to do something similar to a depth first search, in that I would increment a layer counter, to test to see if I am on the same layer, and if I am, to only increment the max counter once. I am a bit confused on the logical flow of the recursive get height, so my implementation makes little to no sense. Can someone point me in the right direction to information regarding the breakdown of the get height recursive function, or assist in correcting my poor attempt at doing what I intended? Thanks!
I'm not really sure, what you want to achieve, but here's a shot:
void getHeight(struct node* node, int &max, int layer) {
if (!node) return;
if (layer>max) {
max = layer;
}
getHeight(node->left, max, layer+1);
getHeight(node->right, max, layer+1);
}
You need to initialize max to 0 before calling getHeight.

C++ return a const pointer inside a none const pointer function

I have coded this function to find the shallowest leaf in binary search tree it is not the best but it does the job, the leaf have to be returned after it have been found.
it is a necessary condition not to change the function prototype.
my problem is pointed by a comment below
The problem is i am returning a const Pointer inside a none const pointer function, i look before posting the question, all of the question where functions inside of classes, I have not studied them so I don't know if it is the same for functions outside of classes, is there any workaround for the problem ?
struct Node {
int _data;
struct Node *_left;
struct Node *_right;
};
//-----------------------------------------------------------------------------------
struct Node *min_depth_leaf(const struct Node *root, int &depth) {
int left_depth;
int right_depth;
if (root == NULL) {
depth = INT32_MAX;
return NULL;
} else if (root->_left == NULL && root->_right == NULL) {
depth = 0;
return root;//<-------------- The problem lays here
} else if (root->_left != NULL || root->_right != NULL) {
struct Node *left_node = min_depth_leaf(root->_left, left_depth);
struct Node *right_node = min_depth_leaf(root->_right, right_depth);
if (right_depth < left_depth) {
right_depth += 1;
depth = right_depth;
return right_node;
} else {
left_depth += 1;
depth = left_depth;
return left_node;
}
}
return NULL;
}
Two ways can be used. The first will help maintain a good project and the second will propagate undefined behaviours , giving an unstable software that behaves differently in the same situatuion.
The first way is to return a copy of the const Node, thus allowing the API user of min_depth_leaf to modify the returned copy value, without modifying the original value in the tree, code will be like:
#include<cstdlib>
struct Node {
int _data;
struct Node *_left;
struct Node *_right;
};
//-----------------------------------------------------------------------------------
struct Node *min_depth_leaf(const struct Node *root, int &depth) {
int left_depth;
int right_depth;
if (root == NULL) {
depth = INT32_MAX;
return NULL;
} else if (root->_left == NULL && root->_right == NULL) {
depth = 0;
// return a copy
Node * p = new Node();
p->_data=root->_data;
p->_left = root->_left;
p->_right = root->_right;
return p;
} else if (root->_left != NULL || root->_right != NULL) {
struct Node *left_node = min_depth_leaf(root->_left, left_depth);
struct Node *right_node = min_depth_leaf(root->_right, right_depth);
if (right_depth < left_depth) {
right_depth += 1;
depth = right_depth;
return right_node;
} else {
left_depth += 1;
depth = left_depth;
return left_node;
}
}
return NULL;
}
The other way (to be avoided) is to cast the const value to non const, causing undefined behaviors (UB), for example:
If the API user deletes the returned Node from min_depth_leaf that is returned it will be deleted from the tree.
if the API user creates the tree on stack in a function f1() and then gets the result of the min_depth_leaf in another function f2(), he will be surprised that as soon as f2() ends, the returned node will be deleted from stack, even though f1() is still not ended, so f1() will get garbage when accessing it .
This way is by using const_cast
return const_cast<Node *>(root); //never use this
Without changing the function's signature the only way to solve this problem is with const_cast:
return const_cast<Node*>(root);
Since your code looks like C rather than C++ to me, a C-style cast may be more appropriate:
return (struct Node*)root;
In any case changing the function signature is a way cleaner approach. If you make your function a template, it will work with both const and non-const nodes:
template<typename T> T* min_depth_leaf(T* root, int &depth)

search function causes program to crash

I have been going through the debugger but can't seem to pinpoint exactly what is going wrong. I have come to my own conclusion i must be missing a nullptr check somewhere or something. If anyone can provide some help it would be greatly appreciated.
error message from debugger
error msg
which looks like makes the program crash on this line:
if (node->children_[index] == nullptr) {
search function
Node* search(const string& word, Node* node, int index) const {
Node* temp;
//same as recurssive lookup just difference is returns node weather terminal or not
if (index < word.length()) {
index = node->getIndex(word[index]);
if (node->children_[index] == nullptr) {
return nullptr;
}
else {
temp = search(word, node->children_[index], index++);
}
}
return temp; // this would give you ending node of partialWord
}
Node struct for reference
struct Node {
bool isTerminal_;
char ch_;
Node* children_[26];
Node(char c = '\0') {
isTerminal_ = false;
ch_ = c;
for (int i = 0; i < 26; i++) {
children_[i] = nullptr;
}
}
//given lower case alphabetic charachters ch, returns
//the associated index 'a' --> 0, 'b' --> 1...'z' --> 25
int getIndex(char ch) {
return ch - 'a';
}
};
Node* root_;
int suggest(const string& partialWord, string suggestions[]) const {
Node* temp;
temp = search(partialWord, root_, 0);
int count = 0;
suggest(partialWord, temp, suggestions, count);
return count;
}
Might be a very simple thing. Without digging I am not sure about the rank of the -> operator versus the == operator. I would take a second and try putting parenthesis around the "node->children_[index] == nullptr" part like this:
(node->children_[index]) == nullptr
just to make sure that the logic runs like you seem to intend.
Dr t
I believe the root cause is that you're using index for two distinct purposes: as an index into the word you're looking for, and as an index into the node's children.
When you get to the recursion, index has changed meaning, and it's all downhill from there.
You're also passing index++ to the recursion, but the value of index++ is the value it had before the increment.
You should pass index + 1.
[An issue in a different program would be that the order of evaluation of function parameters is unspecified, and you should never both modify a variable and use it in the same parameter list. (I would go so far as to say that you should never modify anything in a parameter list, but many disagree.)
But you shouldn't use the same variable here at all, so...]
I would personally restructure the code a little, something like this:
Node* search(const string& word, Node* node, int index) const {
// Return immediately on failure.
if (index >= word.length())
{
return nullptr;
}
int child_index = node->getIndex(word[index]);
// The two interesting cases: we either have this child or we don't.
if (node->children_[child_index] == nullptr) {
return nullptr;
}
else {
return search(word, node->children_[child_index], index + 1);
}
}
(Side note: returning a pointer to a non-const internal Node from a const function is questionable.)

Count nodes with specific number of children in a binary tree?

I have this challenging exercise I got from a book about c++, and i'm not sure how to tackle this problem.
I must define a function called treeNodeCount() which returns the number of nodes in a binary tree (easy enough), and I also have to define an overloaded function that takes an int(0,1, or 2) which represents the number of children, and the function should return the nodes that have that specific number of children.
treeNodeCount should both use a function called nodeCount(elemType root) to do the recursion necessary to count the nodes(so basically all the work).
challenge number one says that I can add a second parameter to nodeCount which takes the number of children for the nodes that we want to count.
Challenge number two says that we cannot use a second parameter (this is the tough part)
I was able to do challenge one and here is what I came up with:
template <class elemType>
int binaryTreeType<elemType>::nodeCount(nodeType<elemType> *p, int a ) const
{
if (p == NULL){
return 0;
}
else if (a == 0 && p->lLink == NULL && p->rLink == NULL){
return 1 + nodeCount(p->lLink, a) + nodeCount(p->rLink, a);
}
else if (a == 1 && (p->lLink != NULL ^ p->rLink != NULL)){
return 1 + nodeCount(p->lLink, a) + nodeCount(p->rLink, a);
}
else if (a == 2 && p->lLink != NULL && p->rLink != NULL){
return 1 + nodeCount(p->lLink, a) + nodeCount(p->rLink, a);
}
else if (a == -1){
return nodeCount(p->lLink, a) + nodeCount(p->rLink, a) + 1;
}
return nodeCount(p->lLink, a) + nodeCount(p->rLink, a);
}
template <class elemType>
int binaryTreeType<elemType>::treeNodeCount(int a) const{
return nodeCount(root, a);
}
This seems to work fine but i am convinced that there has to be a better way.
I was not able to do challenge 2 though, and i have no idea what to do (is it even possible)
You can scrunch down your logic and make it a bit more straightforward by implementing a function to return the number of children given a node.
template <class elemType>
int nodeSize(nodeType<elemType>* node) const
{
int count = 0;
if (node->lLink)
++count;
if (node->rLink)
++count;
return count;
}
template <class elemType>
int binaryTreeType<elemType>::nodeCount(nodeType<elemType>* node, int count) const
{
if (node)
{
if (nodeSize(node) == count || count == -1)
return nodeCount(node->lLink, count) + nodeCount(node->rLink, count) + 1;
return nodeCount(node->lLink, count) + nodeCount(node->rLink, count);
}
return 0;
}
For the second challenge, you need a stack to avoid recursion.
template <class elemType>
int binaryTreeType<elemType>::treeNodeCount(int count) const
{
stack<nodeType<elemType>*> node_stack;
node_stack.push(root);
int num_matches = 0;
while (!stack.empty())
{
nodeType<elemType>* node = node_stack.top();
node_stack.pop();
if (node)
{
if (nodeSize(node) == count || count == -1)
++num_matches;
node_stack.push(node->lLink);
node_stack.push(node->rLink);
}
}
return num_matches;
}
Edit: fixed a goof in the above recursive version. Thanks to David Rodriguez for pointing it out.

Ternary Search Tree

struct Ternary {
char current;
bool wordend;
Ternary* left;
Ternary* mid;
Ternary* right;
Ternary(char c='#',Ternary* l=NULL, Ternary* m=NULL, Ternary* r=NULL,bool end=false)
{
wordend=end;
current=c;
left=l;
mid=m;
right=r;
}
};
void add(Ternary* t, string s, int i) {
if (t == NULL) {
Ternary* temp = new Ternary(s[i],NULL,NULL,NULL,false);
t=temp;
}
if (s[i] < t->current) {
add(t->left,s,i);
}
else if (s[i] > t->current) {
add(t->right,s,i);
}
else
{
if ( i + 1 == s.length()) {
t->wordend = true;
}
else
{
add(t->mid,s,i+1);
}
}
}
When I add sequence of words using add() the string are getting printed inside
if(t==NULL) segment but tree isn't getting formed i.e nodes are not getting linked.
t=temp;
This line has no effect outside of the add() function. The caller's pointer is not updated.
You could change your function to return a Ternary* (return t in this case at the end of it), and change the call sites to:
Ternary *tree = 0;
tree = add(tree, "hello", 1);
tree = add(tree, "bye", 1);
...
Just a little trick will do:
Replace:
void add(Ternary* t, string s, int i)
With:
void add(Ternary*& t, string s, int i)
That's cleaner than passing and then reading output like this:
tree = add(tree, "bye", 1);
When in C++, make use of their references :) In C you would change the function signature to:
void add(Ternary** t, string s, int i)
and remember to correct t in relevant places.
Well, C++ is clearly cleaner :)