Binary Search Tree implementation in C++ - c++

#include <iostream>
using namespace std;
class Node{
public:
int data;
Node* left_child;
Node* right_child;
Node(int x){
data = x;
left_child = NULL;
right_child = NULL;
}
};
class BST{
public:
//Initially root is null
Node* root = NULL;
void insert(Node* node, int data){
if(node == NULL){
node = new Node(data);
return;
}
if(data < node->data){
insert(node->left_child,data);
}
else if(data > node->data){
insert(node->right_child,data);
}
}
void just_insert(int data){
insert(root,data);
}
void print(Node* node){
if(node == NULL){
return;
}
cout<<node->data<<" ";
print(node->left_child);
print(node->right_child);
}
void just_print(){
print(root);
}
};
int main() {
//For fast IO
ios_base::sync_with_stdio(false);
cin.tie(NULL);
int n,x;
cin>>n;
BST bst = BST();
for(int i=0; i<n; i++){
cin>>x;
bst.just_insert(x);
}
bst.just_print();
return 0;
}
What is wrong with this implementation of BST ? I am giving 8 values as input:
8
3
5
1
6
8
7
2
4
But when I invoke the print function. I do not get any output.
Am I missing out on some pointer logic ? The insert function goes recursively down the tree, to find a place to insert the value
The print function also works recursively.

Lets take a look at these lines from the insert function:
if(node == NULL){
node = new Node(data);
return;
}
The problem here is that the argument node is passed by value and is like any other local variable, and like any other local variable it will go out of scope once the function returns, and all changes to the variable will be lost.
What you need is to pass the pointer by reference, like
void insert(Node*& node, int data){ ... }
// ^
// Note ampersand here

You never assign to root in your BST class because your assignment to node in the insert class is not visible outside the insert function. You can fix this by passing the Node pointer by reference to the insert function:
void insert(Node*& node, int data)

Related

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.

Binary Search Tree leaf count issue

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.

Unable to change the pointer value in class

I am trying to build a BST in C++, the root node inside class was not affecting when in call insert() function, it remains NULL.
I am passing root to insert_tree() function when I need to insert data into the tree but when I try to print root value inside insert_tree it always returning NULL
#include <iostream>
struct node
{
int value;
node *left;
node *right;
};
class bst
{
private:
node *root;
node* insert(node* parent,int value)
{
if(parent== NULL){
parent = new node;
parent->value = value;
parent->left = parent->right = NULL;
}
else if(parent->value>value){
parent->left = insert(parent->left,value);
}
else{
parent->right=insert(parent->right,value);
}
return parent;
}
void display(node* parent){
if(parent != NULL){
display(parent->left);
std::cout << parent->value <<"\t";
display(parent->right);
}
}
public:
bst(){
root = NULL;
}
void insert(int value){
root = insert(root,value);
}
void display(){
display(root);
}
};
int main(int argc, char const *argv[])
{
bst b1;
b1.insert(10);
b1.insert(1);
b1.insert(11);
b1.insert(9);
b1.display();
return 0;
}
I would suggest you read about BST first here and learn how insertion is done in a BST. First of all the algorithm is wrong and secondly, use pass by reference in insert_tree() function instead of pass by value. As you are passing by value, so the value of root doesn't change.

delete a node in the middle of a single linked list, given only access to that node

This is an interview question in "Cracking the coding interview". My code and test cases are here:
#include<iostream>
using namespace std;
struct node
{
int data;
node* next;
};
node* init(int a[], int n);
void remove(node* & c);
void printList(node* head);
int main()
{
int a[]={0,1,2,3,4,5,6,7,8,9};
node* testHead=init(a, 10);
printList(testHead);
cout<<endl;
int nth=9;
node *c=testHead;
for(int i=0; i<nth; i++)
{
c=c->next;
}
remove(c);
printList(testHead);
system("PAUSE");
return 0;
}
node* init(int a[], int n)
{
node *head, *p;
for(int i=0; i<n; i++)
{
node *nd=new node();
nd->data=a[i];
if(i==0)
{
head=nd;
p=nd;
}
else
{
p->next=nd;
p=nd;
}
}
return head;
}
void remove(node* & c)
{
if(c==NULL)
return;
node* tmp=c->next;
if(tmp==NULL)
{
delete c;
c=NULL;
}
else
{
c->data=tmp->data;
c->next=tmp->next;
delete tmp;
}
}
void printList(node* head)
{
while(head!=NULL)
{
cout<<head->data<<" ";
head=head->next;
}
}
Here in the main function, I tried to delete the last node, with the data value 9.
However, even in the function "remove", I checked the last node and if it is, I set it to NULL, the output will produce an error.
Can anyone tell me why this happen?
Thanks.
The problems are actually as follows:
You should make the last node of list point to NULL while building the list.
When you delete the last node in the linked list, the previous node -> next becomes a dangling pointer. This pointer has to be made to point to NULL. Since you do not have its address, you will again have to traverse this list from the head node till you get the address of the node prior to the node to be deleted.
void remove(node* & c) // --> 1
{
if(c==NULL)
return;
node* tmp=c->next;
if(tmp==NULL)
{
delete c; // --> 2
c=NULL; // --> 3
}
else
{
c->data=tmp->data;
c->next=tmp->next;
delete tmp;
}
}
This is the thing:
When you pass in as a pointer, you does not necessary to pass in as a reference. It is redundant. //Check #WhozCraig comment for correction
delete releases c allocated memory
Therefore, you cannot assign a NULL to c
Other word, how can you assign NULL to a variable that has been released?

BST Insert C++ Help

typedef struct treeNode {
treeNode* left;
treeNode* right;
int data;
treeNode(int d) {
data = d;
left = NULL;
right = NULL;
}
}treeNode;
void insert(treeNode *root, int data) {
if (root == NULL) {
cout << &root;
root = new treeNode(data);
}
else if (data < root->data) {
insert(root->left, data);
}
else {
insert(root->right, data);
}
}
void inorderTraversal(treeNode* root) {
if (root == NULL)
return;
inorderTraversal(root->left);
cout<<root->data;
inorderTraversal(root->right);
}
int main() {
treeNode *root = new treeNode(1);
cout << &root << endl;
insert(root, 2);
inorderTraversal(root);
return 0;
}
So I'm pretty tired, but I was whipping some practice questions up for interview prep and for some reason this BST insert is not printing out that any node was added to the tree. Its probably something im glossing over with the pointers, but I can't figure it out. any ideas?
void insert(treeNode *root, int data) {
if (root == NULL) {
cout << &root;
root = new treeNode(data);
}
This change to root is lost as soon as the function ends, it does not modify the root passed as argument but its own copy of it.
Take note that when u insert the node, use pointer to pointer (pointer alone is not enough):
So, here is the fixed code:
void insert(treeNode **root, int data) {
if (*root == NULL) {
cout << root;
*root = new treeNode(data);
}
else if (data < (*root)->data) {
insert(&(*root)->left, data);
}
else {
insert(&(*root)->right, data);
}
}
And in main:
int main() {
treeNode *root = new treeNode(1);
cout << &root << endl;
insert(&root, 2);
inorderTraversal(root);
return 0;
}
Your logic is correct!
The only issue is that when you create a local variable, even if it is a pointer, its scope is local to the function. In your main:
...
insert(root, 2);
...
function call sends a copy of the root which is a pointer to treeNode (not the address of root). Please note that
void insert(treeNode *root, int data)
gets a treeNode pointer as an argument (not the address of the pointer). Attention: This function call may look like "call by pointer" (or reference) but it is actually "call by value". The root you define in the main function and the root inside the insert method have different addresses in the stack (memory) since they are different variables. The former is in main function stack in the memory while the latter is in insert method. Therefore once the function call insert finishes executing, its stack is emptied including the local variable root. For more details on memory refer to: stacks/heaps.
Of course the data in the memory that you allocated using:
*root = new treeNode(data);
still stays in the heap but you have lost the reference to (address of) it once you are out of the insert function.
The solution is either passing the address of original root to the function and modifying it (as K-ballo and dip has suggested) OR returning the modified local root from the function. For the first approach please refer to the code written by dip in his/her answer.
I personally prefer returning the modified root from the function since I find it more convenient especially when implementing other common BST algorithms. Here is your function with a slight modification of your original code:
treeNode* insert(treeNode *root, int data) {
if (root == NULL) {
root = new treeNode(data);
}
else if (data < root->data) {
root->left=insert(root->left, data);
}
else {
root->right=insert(root->right, data);
}
return treeNode;
}
The function call in main will be:
int main() {
treeNode *root = new treeNode(1);
cout << &root << endl;
root = insert(root, 2);
inorderTraversal(root);
return 0;
}
Hope that helps!
After a while seeing some complicated methods of dealing with the Binary tree i wrote a simple program that can create, insert and search a node i hope it will be usefull
/*-----------------------Tree.h-----------------------*/
#include <iostream>
#include <queue>
struct Node
{
int data;
Node * left;
Node * right;
};
// create a node with input data and return the reference of the node just created
Node* CreateNode(int data);
// insert a node with input data based on the root node as origin
void InsertNode (Node* root, int data);
// search a node with specific data based on the root node as origin
Node* SearchNode(Node* root, int data);
here we define the node structure and the functions mentioned above
/*----------------------Tree.cpp--------------*/
#include "Tree.h"
Node* CreateNode(int _data)
{
Node* node = new Node();
node->data=_data;
node->left=nullptr;
node->right=nullptr;
return node;
}
void InsertNode(Node* root, int _data)
{
// create the node to insert
Node* nodeToInsert = CreateNode(_data);
// we use a queue to go through the tree
std::queue<Node*> q;
q.push(root);
while(!q.empty())
{
Node* temp = q.front();
q.pop();
//left check
if(temp->left==nullptr)
{
temp->left=nodeToInsert;
return;
}
else
{
q.push(temp->left);
}
//right check
if(temp->right==nullptr)
{
temp->right=nodeToInsert;
return;
}
else
{
q.push(temp->right);
}
}
}
Node* SearchNode(Node* root, int _data)
{
if(root==nullptr)
return nullptr;
std::queue<Node*> q;
Node* nodeToFound = nullptr;
q.push(root);
while(!q.empty())
{
Node* temp = q.front();
q.pop();
if(temp->data==_data) nodeToFound = temp;
if(temp->left!=nullptr) q.push(temp->left);
if(temp->right!=nullptr) q.push(temp->right);
}
return nodeToFound;
}
int main()
{
// Node * root = CreateNode(1);
// root->left = CreateNode(2);
// root->left->left = CreateNode(3);
// root->left->left->right = CreateNode(5);
// root->right = CreateNode(4);
// Node * node = new Node();
// node = SearchNode(root,3);
// std::cout<<node->right->data<<std::endl;
return 0;
}