Binary Search Tree leaf count issue - c++

I desperately need help finding the problem in my code, I'm sure it's narrowed down to the countLeaves function. I can't seem to get it to print out no matter how I alter it. I'm pretty new to C++ but I'd really appreciate anything anyone can offer me! I will post the header, function, and main in that order.
#include <iostream>
//#include<stack>
//#include<queue>
#ifndef BSTFunction
#define BSTFunction
using namespace std;
typedef int num;
class Node{
public:
num info;
Node* left;
Node* right;
Node(); // Valuetype to num
Node(num);
};
class BST{
public:
Node* findNode(num);
Node* findParent(num);
Node* findrightnode(Node*);
void inorder(Node*);
Node* root;
Node* curr;
//Was public:
BST();
void insert(num);
void inorderTraversal(); //was traverse
num search();
void custom_print();
int countLeaves(Node* T);
};
#endif
Function.cpp
#include <iostream>
#include <queue>
#include "BSTFunction.hpp"
Node::Node(){
left=right=NULL;
}
Node::Node(num val){
info=val;
left=right=NULL;
}
//constructor
BST::BST(){
root=curr=NULL;
}
//insert a node with value val in tree
void BST::insert(num val){
if(root==NULL)
root = new Node(val);
else{
Node* p =findNode(val);
if(p==0) {
//cout<<"fine1";
Node* parent=root;
if (p != root)
parent = findParent(val);
if(val>parent->info) parent->right=new Node(val);
else parent->left=new Node(val);
}//cout<<"fine2";
}
}
//remove the node if value is val
//fins node with a value key
Node* BST::findNode(num key){
Node* p =root;
while((p!=NULL)&&(p->info!=key)){
if(key<p->info)p=p->left;
else p=p->right;
}
return p;
}
//find parent of a node with value key
Node* BST::findParent(num key){
Node* p =root;
Node* q=0;
while((p!=NULL)&&(p->info!=key)){
q=p;
if(key<p->info)p=p->left;
else p=p->right;
}
return q;
}
//finds the most right of a node p(means immediate succesor of p in inorder representation)
//Node* BST::findrightnode(Node* p){
// Node* righty=p;
// while(righty->right!=NULL)
// righty=righty->right;
// return righty;
//}
void BST::inorder(Node* p){
if(p!=NULL){
inorder(p->left);
cout<<p->info<<" ";
inorder(p->right); }
}
void BST::inorderTraversal(){
cout<<endl<<"Inorder: ";
inorder(root);
cout<<endl;
}
//to print tree hightwise i.e. all nodes at h1, then all nodes at h2, then at h3
void BST::custom_print(){
//Node* temp;
if(root==NULL)
return;
queue<Node*> Q;
Q.push(root);
//Q.push(NULL);
while(!Q.empty()){
curr=Q.front();
cout<<curr<<" ";
Q.pop();
Q.push(curr->left);
Q.push(curr->right);
}
}
int BST::countLeaves(Node *T)
{
if(T ==NULL) //if T is empty, return0
{
return(0);
}
else if(T -> left == NULL && T-> right == NULL) //if T has0 children, then it is a leaf
{
return(1);
}
else
{
return countLeaves(T -> left) + countLeaves(T -> right); //recursive call to find more leaves
}
}
Main.cpp
#include<iostream>
#include "BSTFunction.hpp"
int main()
{
BST leaves;
leaves.insert(24);
leaves.insert(43); //The code will take all of these numbers entered into the main function and put them in traversal order, much like it could under any order (post or pre) if needed. (Note to self: Not needed for this assignment)
leaves.insert(82);
leaves.insert(22);
leaves.insert(12);
leaves.insert(92);
leaves.insert(68);
leaves.insert(20);
leaves.insert(4);
cout << "These are the in order leaves for the Bianary Search Tree. " << endl;
leaves.inorderTraversal();
cout << "The number of leaves are: " << endl;
leaves.countLeaves()
//leaves.custom_print();
return 0;
}

The problem in your code is that you have an argument in your countLeaves() function-
int BST::countLeaves(Node *T)
When you call this function from your main, it doesn't have an
argument to give to countLeaves(). It throws an error as it doesn't
receive any parameter.
As for the solution, you'll have to create a Node object in your main and send it as an argument. You'll have to worry about what and how you are going to do all this. There seems to be a few errors both in logic and syntax. (I commented your countLeaves() call and it threw many errors.
Recommend using debugger.
Try to print values and "Function entered" print statements to make it easier to find mistakes in your program if you cannot use debugger at the moment.
Hope this was helpful.

Related

Inserting elements in a bst using recursion

I'm trying to add elements enter by the user in a BST.For this I've used 2 functions, one is used to create the function and other is just used to insert element to the tree. One is a pre-order function that is used to check if insertion is done or not Initially I tried to add elements manually.Its not printing all inserted values.
The overall layout
struct Node{
int data;
struct Node* left;
struct Node* right;
};
void Inorder(struct Node* root){
if(root==NULL){
return;
}
else{
Inorder(root->left);
cout<<root->data<<" ";
Inorder(root->right);
}
}
struct Node* create_node(int data){
struct Node* node=(struct Node*) malloc(sizeof(struct Node));
node->data=data;
node->left=NULL;
node->right=NULL;
return node;
}
The problem code:-
struct Node* insert(struct Node* root,int data){
static struct Node* prev=NULL;
if(root==NULL && prev==NULL){
return create_node(data);
}
if(root->data==data){
return root;
}
else{
if(root==NULL){
struct Node* ptr=create_node(data);
if(prev->data>data){
prev->left=ptr;
return root;
}
else{
prev->right=ptr;
return root;
}
}
else{
if(root->data>data){
prev=root;
insert(root->left,data);
}
else{
prev=root;
insert(root->right,data);
}
}
}
}
MAIN
int main()
{
struct Node* root=NULL;
root=insert(root,5);
Inorder(root);
cout<<endl;
insert(root,3);
Inorder(root);
insert(root,10);
Inorder(root);
return 0;
}
One thing I noticed that prev is static once we call insert for inserting next element(here 3) it won't roll over from start again because it is declared static.To overcome that
Tried to optimize the problem code by making prev as global and making null in main every time I call insert function in the main(), The optimised code is as follows:
#include <iostream>
#include<stdlib.h>
using namespace std;
static struct Node* prev=NULL;
struct Node{
int data;
struct Node* left;
struct Node* right;
};
void Inorder(struct Node* root){
if(root==NULL){
return;
}
else{
Inorder(root->left);
cout<<root->data<<" ";
Inorder(root->right);
}
}
struct Node* create_node(int data){
struct Node* node=(struct Node*) malloc(sizeof(struct Node));
node->data=data;
node->left=NULL;
node->right=NULL;
return node;
}
struct Node* insert(struct Node* root,int data){
if(root==NULL && ::prev==NULL){
return create_node(data);
}
if(root->data==data){
return root;
}
else{
if(root==NULL){
struct Node* ptr=create_node(data);
if(::prev->data>data){
::prev->left=ptr;
return root;
}
else{
::prev->right=ptr;
return root;
}
}
else{
if(root->data>data){
::prev=root;
insert(root->left,data);
}
else{
::prev=root;
insert(root->right,data);
}
}
}
}
int main()
{
struct Node* root=NULL;
root=insert(root,5);
Inorder(root);
cout<<endl;
::prev=NULL;
insert(root,3);
Inorder(root);
::prev=NULL;
insert(root,10);
Inorder(root);
return 0;
}
This is not how insertion into a BST is supposed to work. You don't need a prev pointer at all.
One of the issues in your code is that you don't use the return value of the recursive call, which at some point is going to be the pointer to a new node! You should really assign that return value to either the left or right member of the current node.
Also, the following if condition will never be true, as at that point it was already guaranteed that root is not NULL:
else{
if(root==NULL){
The correct code is actually quite simple:
struct Node* insert(struct Node* root, int data){
if (root == NULL) {
root = create_node(data);
} else if (root->data > data) {
root->left = insert(root->left, data);
} else if (root->data < data) {
root->right = insert(root->right, data);
}
return root;
}
I would also add some line breaks to the output in your main code:
int main()
{
struct Node* root = NULL;
root = insert(root, 5);
Inorder(root);
cout << endl;
insert(root, 3);
Inorder(root);
cout << endl;
insert(root, 10);
Inorder(root);
cout << endl;
return 0;
}
The issue that I noticed in my code (Unfortunately unable to upload the snippet). was in the part mentioned below.
if(root->data==data){
return root;
}
Firstly let me explain the recursion function, at beginning the root would be null at insertion(here inserting 5 as root) so first condition will be satisfied i.e.
if(root==NULL && ::prev==NULL){
return create_node(data);
}
and the function would return,now I set the global variable prev as NULL because I want to traverse again from the root of the tree to add the next element.
Now once we try to add another element (here adding element 3). This condition
if(root==NULL && ::prev==NULL){
return create_node(data);
}
won't be true, now the thought process while writing the logic was checking if at some stage while traversing down the tree if we encounter node with same value then we'll return the root and terminate the function. This is what I tried to implement .
Here's the code if you could relate(Problem Code Snippet)
else if(root->data==data){
return root;
}
No doubt approach is fine but I forgot to add one condition(actually I preempted that at this stage the root won't be NULL) but root can be NULL.
Because of this we will face segmentation fault error (in debugger mode -> which helped me to find the error in my code!).
So the correct code would be:
else if(root && root->data==data){// or if(root!=NULL && root->data=data)
return root;
}
Rest of the code remains unaltered
So to sum up when traversing through tree we return true for all conditions and once we reach NULL then since first condition won't we satisfied as prev!=NULL, so it comes to next condition root->data==data but here root=NULL so we get
segmentation fault error and function never encounters ROOT==NULL which was designed for this purpose only i.e. to add/insert element in the tree as everything seems fine on traversing the tree. So to over come this problem I modified my else if condition i.e. else if(root && root->data==data)
so the full function code is as follows:
struct Node* insert(struct Node* root,int data){
if(root==NULL && ::prev==NULL){
return create_node(data);
}
else if(root && root->data==data){
return root;
}
else{
if(root==NULL){
struct Node* ptr=create_node(data);
if(::prev->data>data){
::prev->left=ptr;
return root;
}
else{
::prev->right=ptr;
return root;
}
}
else{
if(root->data>data){
::prev=root;
insert(root->left,data);
}
else{
::prev=root;
insert(root->right,data);
}
}
}
}
PS: The code was executed for many trees including one mentioned in the question and got the expected results i.e. Inorder was a sorted array which depicts that insertion was done correctly.

Try tree inplementation

Try to make tree , have a some troubles, first it's print function - it's print not integers that i put, but print random numbers;
Another trouble its append child - its works only one times;
Will be happy if you will help me with this task.
And also give some good articles about linked lists, trees on c and c++;
#include <iostream>
#include <stdio.h>
using namespace std;
struct Node
{
void* m_pPayload;
Node* m_pParent;
Node* m_Children;
};
struct Person
{
int m_Id;
};
//typedef bool (*NodeComparator)(void* pValue, void* pPayload);
/*bool Comp(void* pValue, void* pPayload)
{
Person* pVal = (Person*)pValue;
Person* pPay = (Person*)pPayload;
if (pVal->m_Id == pPay->m_Id)
return true;
else
return false;
}
*/
Node* NewNode(void* pPayload)
{
Node* pNode = new Node;
pNode->m_pParent = nullptr;
pNode->m_Children = 0;
pNode->m_pPayload = pPayload;
return pNode;
}
Person* NewPerson(int id)
{
Person* p = new Person;
p->m_Id = id;
return p;
}
//Node* FindNode(Node* pParent, Node* m_pPayload, NodeComparator comparator);
void AppendChild(Node* pParent, Node* pNode)
{
if (pParent->m_Children == NULL)
pParent->m_Children = pNode;
}
void print(Node* head)
{
Node* current_node = head;
while (current_node != NULL)
{
printf("%d\n ", current_node->m_pPayload);
current_node = current_node->m_Children;
}
}
int main()
{
Node* T = new Node;
T = NewNode(NewPerson(5));
AppendChild(T, NewNode(NewPerson(11)));
AppendChild(T, NewNode(NewPerson(15)));
print(T);
}
printf("%d\n ", current_node->m_pPayload)
is incorrect. %d wants an integer and it's being given a pointer. The results will be unusual, and likely appear to be random garbage.
printf("%d\n ", ((Person*)current_node->m_pPayload)->m_Id);
^ ^
| Get id from Person
treat payload pointer as pointer to Person
will solve the immediate problem.
Your code actually seems to be pretty messed up with a lot of things going on, here sharing my own commented code from few years back, hope it helps
#include <bits/stdc++.h>
using namespace std;
// Single node representation
struct node {
int data;
node *left, *right;
};
// Declaring temp for refference and root to hold root node
node *root, *temp;
// This function only generates a node and return it to the calling function with data stored in it
node* generateNode(int data){
temp = new node();
temp->data = data;
temp->left = temp->right = NULL;
return temp;
}
// This function actually adds node to the tree
node* addNode(int data, node *ptr = root){
// If the node passed as ptr is NULL
if(ptr == NULL){
ptr = generateNode(data);
return ptr;
}
// Condition to check in which side the data will fit in the tree
else if(ptr->data < data)
//if its in right, calling this function recursively, with the right part of the tree as the root tree
ptr->right = addNode(data, ptr->right);
else
//In case the data fits in left
ptr->left = addNode(data, ptr->left);
//Note: if there is no data in left or roght depending on the data's valid position, this function will get called with NULL as second argument and then the first condition will get triggered
//returning the tree after appending the child
return ptr;
}
//Driver function
int main ()
{
int c, data;
for (;;){
cin >> c;
switch(c){
case 1:
cout << "enter data: ";
cin >> data;
//Updating root as the tree returned by the addNode function after adding a node
root = addNode(data);
break;
default:
exit(0);
break;
}
}
return 0;
}
Please find below a piece of code that should easily get you started. It compiles and it traverse the tree using recursion.
#include <iostream>
#include <vector>
#include <stdio.h>
using namespace std;
struct Node
{
int m_Id;
vector<Node*> m_Children;
Node(const int& id){
m_Id = id;
}
void AppendChild(Node* pNode) {
m_Children.push_back(pNode);
}
void Print() {
printf("%d\n ", m_Id);
}
};
void traverse(Node* head)
{
Node* current_node = head;
current_node->Print();
for(int i = 0; i<current_node->m_Children.size(); i++) {
traverse(current_node->m_Children[i]);
}
}
int main()
{
Node* T0 = new Node(0);
Node* T10 = new Node(10);
T10->AppendChild(new Node(20));
Node* T11 = new Node(11);
Node* T12 = new Node(12);
Node* T22 = new Node(22);
T22->AppendChild(new Node(33));
T12->AppendChild(T22);
T0->AppendChild(T10);
T0->AppendChild(T11);
T0->AppendChild(T12);
traverse(T0);
}
First for printing the node value
Talking about the current mistake that you had committed is in the above code is:
You have not mentioned its pointer to its child (specifically right or left). Due to which it is showing garbage value every time.
For e.g.: print( node->left);
Since you need to type caste it properly to show the data of data.
For e.g.: printf("%d\n ", ((Person*)current_node->m_pPayload)->m_Id);
There is a specific direction in which you want to print data. For trees, there are three directions in which you can print the data of the node and they are as follow:
Left order or Inorder traversal
Preorder traversal
Postorder traversal
This can give you better information about traversal.
Secondly for adding the node to a tree
This might help explain it better.

Why isn't my printLevel function working?

I have written this code to do level order traversal of Binary Search tree. Error is only in printLevel function because all other functions are working fine.
#include <queue>
using namespace std;
struct node{
int data;
struct node* left;
struct node* right;
};
struct node* newNode(int data){
struct node* node = new (struct node);
node->data=data;
node->left=NULL;
node->right=NULL;
return (node);
};
struct node* insert (struct node* node, int data){
if (node==NULL){
return (newNode(data));
}
else {
if (data<=node->data) node-> left=insert(node->left,data);
else node->right=insert(node->right,data);
return (node);
}
}
void printLevel(struct node* node){
queue<struct node*> q;
while(node!=NULL){
cout << node->data << " ";
q.push(node->left);
q.push(node->right);
node=q.front();
}
}
int main(){
int n;
cin >>n;
int m;
cin >>m;
struct node* root=newNode(m);
for (int i=0;i<n-1;i++){
cin>>m;
insert(root,m);
}
printLevel(root);
// printPostOrder(root);
// cout <<maxDepth(root);
// debug(maxDepth(root), minValue(root), printTree(root));
//struct node* root=build123();
}
Here is the algorithm: (http://www.geeksforgeeks.org/level-order-tree-traversal/)
printLevelorder(tree)
1) Create an empty queue q
2) temp_node = root /start from root/
3) Loop while temp_node is not NULL
a) print temp_node->data.
b) Enqueue temp_node’s children (first left then right children) to q
c) Dequeue a node from q and assign it’s value to temp_node
I am taking input 3,1,4,2,7,6,5 for 7 nodes. It gets stuck in infinite loop. I have also implemented following two functions based on another method and it is working fine:
void levelOrder(struct node* node, int level ){
if (node==NULL){
return;
}
if (level==1){
cout << node->data;
}
else if (level>1){
levelOrder(node->left,level-1);
levelOrder(node->right,level-1);
}
}
void printLevelOrder(struct node* root){
for (int i=1;i<=maxDepth(root);i++){
levelOrder(root,i);
}
}
It is O(n^2) but above one is O(n). What's wrong with my code? Thanks.
I suspect that your loop termination is wrong.
Instead of node != NULL, you should check to see if !q.empty().
Also, the call q.front does not remove the element from the queue; to do that, you need pop (after calling front).
This code works for me:
void printLevel(struct node* node){
std::queue<struct node*> q;
q.push(node);
while(!q.empty()) {
node=q.front();
q.pop();
if ( node != NULL ) {
std::cout << node->data << " ";
q.push(node->left);
q.push(node->right);
}
}
}

search in a binary tree

I have written the following function to search for a value in a binary tree storing integer values (the function is part of a larger program):
bool tree::search(int num) //the function belongs to class 'tree'
{
node *temp=head; //'head' is pointer to root node
while(temp!=NULL)
{
if(temp->data==num)
break;
if(num>temp->data)
temp=temp->right;
if(num<temp->data)
temp=temp->left;
}
if(temp==NULL)
return false;
else if(temp->data==num)
return true;
}
The problem is: when I search for a value present in the tree, it runs fine. But if I search for a value not present in the tree, the program just hangs, and I have to close it.
One more thing - I know we can implement the search function recursively by passing node *temp as an argument, instead of declaring it inside, and I have done so which caused the program to run correctly, but I want to know what is the problem in the above code.
I am giving the full program here, just in case it makes fault- finding easier( please note that I have written only two functions yet):
#include<iostream>
using namespace std;
struct node
{
int data;
node *left;
node *right;
};
class tree
{
public:
node *head; //pointer to root
int count; //stores number of elements in tree
tree();
void addnode(int);
void deletenode(int);
bool search(int);
int minimum();
int maximum();
void inorder();
void preorder();
void postorder();
void printtree();
int mthlargest(); //finds 'm'th largest element
int mthsmallest(); //finds 'm'th smallest element
void convert(); //converts binary tree to linked list
};
tree::tree()
{
head=NULL;
count =0;
}
void tree::addnode(int num)
{
node *temp= new node;
temp->data=num;
temp->left=NULL;
temp->right=NULL;
node **ptr=&head; //double pointer
while(*ptr!=NULL)
{
if(num>(*ptr)->data)
ptr=&((*ptr)->right);
if(num<(*ptr)->data)
ptr=&((*ptr)->left);
}
*ptr=temp;
}
bool tree::search(int num)
{
node *temp=head;
while(temp!=NULL)
{
if(temp->data==num)
break;
if(num>temp->data)
temp=temp->right;
if(num<temp->data)
temp=temp->left;
}
if(temp==NULL)
return false;
else if(temp->data==num)
return true;
}
int main()
{
tree ob;
ob.addnode(2);
ob.search(2);
ob.search(3);
ob.search(-1);
ob.search(2);
cout<<endl<<endl;
system("pause");
return 0;
}
Side note : I am using Dev C++ compiler and Windows 7 OS.
Put an else and your problem will disappear.
Because after temp = temp->right; you must check temp again but in your original code you immediately test temp->data which may not be a valid pointer.
bool tree::search(int num)
{
node *temp = head;
while (temp != NULL)
{
if (temp->data == num)
break;
if (num > temp->data)
temp = temp->right;
else // <--- Put this 'else' here
if (num < temp->data)
temp = temp->left;
}
if (temp == NULL)
return false;
if (temp->data == num)
return true;
return false;
}
std::set
Use a std::set; it is basically STL's binary tree. If you want to search for something, you would use count, find or lower_bound.
Implementing basic data structures are good exercises, but in production, try to use STL first, as they are implemented by professionals with specific knowledge of the compiler/platform in question. Boost is another great set of data structures and common idioms.

How to find the minimal element of a BST?

I'm a beginner to c++ and am having problems with finding the minimal element of a BST. The BST is implemented in this way:
class Tree{
struct Node {
int Element;
Node *Left, *Right;
Node(int Element) : Element(Element), Left(0), Right(0){}
};
Node *Root;
void InOrder(void(*Action)(int&), Node *Current);
void Destroy(Node *Current);
public:
Tree() : Root(0){}
void Insert(int Element);
void InOrder(void(*Action)(int&)) {InOrder(Action,Root);}
void Destroy() {Destroy(Root);}
};
The InOrder, Destroy and Insert methods are implemented like this:
void Tree::Insert(int Element) {
Node *NewElement = new Node(Element);
if(!Root) Root = NewElement;
else {
Node *Previous, *Current = Root;
while(Current) {
Previous = Current;
if(Element < Current->Element) Current = Current->Left;
else Current = Current->Right;
}
if(Element < Previous->Element) Previous->Left = NewElement;
else Previous->Right = NewElement;
}
}
void Tree::InOrder(void(*Action)(int&),Node *Current) {
if(Current) {
InOrder(Action,Current->Left);
Action(Current->Element);
InOrder(Action,Current->Right);
}
}
void Tree::Destroy(Node *Current) {
if(Current) {
Destroy(Current->Left);
Destroy(Current->Right);
delete Current;
}
}
And the main function and function which I use to print the numbers look like this:
void Print(int &e) {
cout << e << endl;
}
int main() {
Tree t;
while(1) {
int Number;
cout << "Insert number (insert 0 to end): ";
cin >> Number;
if(Number == 0) break;
t.Insert(Number);
}
t.InOrder(Print);
t.Destroy();
getch();
}
As you may noticed, the InOrder method is implemented also, maybe it can be used in some way to help solve my problem... Sorry for my bad English :/
The minimal value would be the first value that calls Action in the above code. Go left as far as you can, and the minimal value you shall find...