I've been tasked with creating an insert method for a Binary Search Tree in C++ from scratch. When I run this in Visual Studio I get no output at all and it exits with code 0. It would seem the else if and else blocks of the insert function are never being run, and I can't figure out why. Any help would be much appreciated, thanks in advance!
#include <iostream>
using std::endl;
using std::cout;
class Node {
public:
int data;
Node* left;
Node* right;
Node(int data) {
this->data = data;
this->left = nullptr;
this->right = nullptr;
}
};
class BinarySearchTree {
public:
Node* root = nullptr;
Node* insert(Node* root, int data) {
if (root == nullptr) {
root = new Node(data);
}
else if (data <= root->data) {
cout << "going left" << endl;
root->left = insert(root->left, data);
}
else {
cout << "going left" << endl;
root->right = insert(root->right, data);
}
return root;
}
};
int main() {
BinarySearchTree bst;
bst.insert(bst.root, 9);
bst.insert(bst.root, 4);
bst.insert(bst.root, 6);
bst.insert(bst.root, 16);
return 0;
}
You're passing the arguments by value in
Node* insert(Node* root, int data) {
root is a copy of bst.root. root = new Node(data); assigns to the copy, not to the original variable. You could use a reference:
Node* insert(Node*& root, int data) {
Related
I'm trying to implement the insertion function used on geeksforgeeks.com but am running into some problems trying to work it into my current code.
I have a vector with the data I need to put into the binary tree. I use this function to pass the numbers into the insertion function:
void populateTree(vector<string> dataVec) {
for (int i = 0; i < dataVec.size(); i++) {
insert(stoi(dataVec[i]), root);
}
}
This is the insertion function:
node* insert(int x, node* node) {
if (node == nullptr)
return newNode(x);
if (x < node->data)
node->left = insert(x, node->left);
else
node->right = insert(x, node->right);
return root;
}
New node function:
node* newNode(int num) {
node* temp = new node;
temp->data = num;
temp->left = temp->right = nullptr;
temp->level = 1;
return temp;
}
Root is a private member within the class which is initialized to nullptr. I'm not sure how I should go about making the first node that comes in from the vector as the root and then keep inserting things beginning from there recursively. Thanks!
The problem in your is related to use of pointer.
Instead of using node* insert(int x, node* node) you should use node* insert(int x, node** node) or node* insert(int x, node*& node) and adopt your code accordingly.
Following is corrected sample code. See it in execution here:
#include <iostream>
#include <vector>
using namespace std;
struct Node
{
int val;
Node* left;
Node* right;
Node(int v)
{
val = v;
left = right = nullptr;
}
};
class Tree
{
Node* root;
Tree()
{
root = nullptr;
}
public:
static void insert(int x, Node*& node)
{
if (node == nullptr)
{
node = new Node(x);
}
else
{
if (x < node->val)
insert(x, node->left);
else
insert(x, node->right);
}
}
static Tree* populateTree(vector<string> dataVec)
{
Tree* t= new Tree();
for (int i = 0; i < dataVec.size(); i++)
{
insert(stoi(dataVec[i]), t->root);
}
return t;
}
static void printTree(Node* node, string s)
{
if(node == nullptr) return;
cout<<s<< "+"<<node->val <<endl;
s += "----";
printTree(node->left,s);
printTree(node->right, s);
}
static void printTree(Tree* t)
{
if(t)
{
printTree(t->root, "");
}
}
};
int main() {
Tree* t = Tree::populateTree({"70", "2", "7", "20", "41", "28", "20", "51", "91"});
Tree::printTree(t);
return 0;
}
Hello I am implementing a binary search tree. I have to find all the elements smaller than a given key applying a binary search:
struct node {
int data;
node* right;
node* left;
};
class binTree {
public:
binTree();
~binTree();
void insert(node**, int);
void inOrder(node**)const;
void preOrder(node**)const;
void postOrder(node**)const;
void delTree();
node* search(node**, int)const;
void search_less(node**, int)const;
};
binTree::binTree() {
}
binTree::~binTree() {
}
void binTree::insert(node** root, int data) {
node* tmp = *root;
if (!tmp) {
tmp = new node;
tmp->data = data;
tmp->right = NULL;
tmp->left = NULL;
*root = tmp;
return;
}
if (data < tmp->data)
insert(&tmp->left, data);
else
insert(&tmp->right, data);
}
void binTree::preOrder(node** root)const {
node* tmp = *root;
if (tmp) {
cout << tmp->data << endl;
preOrder(&tmp->left);
preOrder(&tmp->right);
}
}
void binTree::inOrder(node** root)const {
node* tmp = *root;
if (tmp) {
inOrder(&tmp->left);
cout << tmp->data << endl;
inOrder(&tmp->right);
}
}
void binTree::postOrder(node** root)const {
node* tmp = *root;
if (tmp) {
postOrder(&tmp->left);
postOrder(&tmp->right);
cout << tmp->data << endl;
}
}
node* binTree::search(node** root, int data)const {
node* tmp = *root;
if (tmp) {
if (data == tmp->data) {
cout << "found!" << endl;
return tmp;
}
else
if (data < tmp->data)
search(&tmp->left, data);
else
search(&tmp->right, data);
}
cout << data << ": not found in tree!" << endl;
return NULL;
}
void binTree::search_less(node** root, int key)const
{
node* tmp = *root;
tmp = search(root, key);
}
int main()
{
node* root = NULL;
binTree bt;
bt.insert(&root, 42000);
bt.insert(&root, 41000);
bt.insert(&root, 45000);
bt.insert(&root, 47000);
bt.insert(&root, 42500);
bt.insert(&root, 43000);
bt.insert(&root, 44000);
bt.insert(&root, 40000);
bt.insert(&root, 10000);
bt.insert(&root, 20000);
bt.insert(&root, 30000);
bt.search_less(&root, 42000); // I want to get values smaller than 42000
}
I've tried too much but couldn't figure it out. I want to print all the values below the key entered. Thank you.
Create an accumulator std::vector<T>
Set root node as current node
If current node is nullptr, go to 6 (you're done)
If current node is >= search value, set left node as current node and go to 3
If current node is < search value, accumulate this value and accumulate the entire subtree of the left node. Set right node as current node and go to 3
Return the accumulator
Accumulating the entire left node should be its own function (accumulate_entire_tree or something like that). The recursive function should be steps 3-5. Steps 1-6 are the entire wrapper function. In the end you get three functions:
std::vector<int> search_less_than(const Node& root, int key) const
void accumulate_less_than(const Node* root, int key, std::vector<int>& accumulator) const
void accumulate_entire_tree(const Node* root, std::vector<int>& accumulator) const
Make the last two functions private since they're more implementation details than interface.
You can make something similar to your search function:
void binTree::search_less(node** root, int data) const {
node* tmp = *root;
if (tmp) {
if (data > tmp->data) {
search_less(&tmp->left, data);
cout << tmp->data << endl;
search_less(&tmp->right, data);
} else {
search_less(&tmp->left, data);
}
}
}
Demo
In case the Key is existing then it is straightforward: inside search_less use yur function search to find the key then pass its node to inOrder or postOrder...
If the you want to get values smaller than a non existing key: It is a bit tricky:
If the key is smaller than the root node data then move leftward until data is smaller than the key or equal then pass that node to inOrder or postOrder.
If the key is greater than root then move rightward until a node with data is smaller than or equal to it then do the first step and print.
void binTree::search_less(node** root, int data)const
{
node* tmp = *root;
if (tmp && tmp->data < data)
tmp = tmp->right;
while (tmp && tmp->data >= data)
tmp = tmp->left;
inOrder(&tmp);
}
I've spent some considerable time and effort to find this solution on my own:
void binTree::search_less(node** root, int key)const
{
node* tmp = *root;
if(tmp)
{
search_less(&tmp->left, key);
if(key <= tmp->data)
return;
search_less(&tmp->right, key);
std::cout << tmp->data << ", ";
}
}
int main()
{
node* root = NULL;
binTree bt;
bt.insert(&root, 42000);
bt.insert(&root, 41000);
bt.insert(&root, 45000);
bt.insert(&root, 47000);
bt.insert(&root, 42500);
bt.insert(&root, 43000);
bt.insert(&root, 44000);
bt.insert(&root, 40000);
bt.insert(&root, 10000);
bt.insert(&root, 20000);
bt.insert(&root, 30000);
bt.search_less(&root, 37500);
std::cout << "\nDone!\n";
}
The output:
30000, 20000, 10000,
Done!
[Process completed - press Enter]
I walk left most through recursion until i get to the smallest value in the tree using the "inOrder" method because it get values sorted from small to big. then print it and walk right and check whether the data is greater than or equal to the key, in this case stop and return.
Please tell me whether this is a correct and efficient solution?
I am trying to execute linked list with the below code.But I am unable to figure out the mistake in it.
I got the concept of it but I am failing to implement the same.
Any help is highly appreciated.
#include <iostream>
using namespace std;
struct Node {
int data;
Node *next;
Node(int j) : data(j), next(nullptr) {}
friend ostream &operator<<(ostream &os, const Node &n) {
cout << "Node\n"
<< "\tdata: " << n.data << "\n";
return os;
}
};
void addElement(Node **head, int data){
Node *temp = nullptr;
temp->data = data;
temp->next=nullptr;
Node *cur = *head;
while(cur) {
if(cur->next == nullptr) {
cur->next = temp;
return;
}
cur = cur->next;
}
};
void printList(const Node *head){
const Node *list = head;
while(list) {
cout << list;
list = list->next;
}
cout << endl;
cout << endl;
};
void deleteList(Node *head){
Node *delNode =nullptr;
while(head) {
delNode = head;
head = delNode->next;
delete delNode;
}};
int main() {
Node *list = nullptr;
addElement(&list, 1);
addElement(&list, 2);
printList(list);
deleteList(list);
return 0;
}
after compiling I am getting no error and no output.So I am unable to figure what is going wrong or else my implementation of which is not right!
Here an error straightaway
void addElement(Node **head, int data){
Node *temp = nullptr;
temp->data = data;
temp is null, but you dereference it. It's an error to dereference a null pointer.
I guess you meant this
void addElement(Node **head, int data) {
Node *temp = new Node(data);
which allocates a new Node, initialises it with data and makes temp point to the newly allocated Node.
I am writing a code to return data of a node in BST based on id.
below is my node class:
struct Node{
int id;
string data;
Node *left;
Node *right;
Node();
};
below is my node constructor: I defined id and data in addNode function
Node :: Node(){
this->left = nullptr;
this->right = nullptr;
}
below is my BST class:
class BST{
private:
Node * root = nullptr;
void setRoot(Node *);
Node* getRoot();
public:
Node *addNode(BST *, int);//helper function
Node *addNode(Node *,int);
string getEntry(BST*,int);//helper function
string getEntry(Node*,int);
}
below is my helper functions:
Node *BST::addNode(BST *bst, int val){
addNode(bst->getRoot(),val);
}
string BST::getEntry(BST* bst,int id){
getEntry(bst->getRoot(),id);
}
below is my addNode class:
Node* BST::addNode(Node* root, int val) {
Node *newNode = new Node();
newNode->id = val;
newNode->data = "Number " + to_string(val);
if (root == nullptr) {
if (getRoot() == nullptr){
setRoot(newNode);
}
setCount(getCount()+1);
return newNode;
}
if (root->id > val) {
root->left = addNode(root->left, val);
} else {
root->right = addNode(root->right, val);
}
return root;
}
below is my getEntry class:
string BST::getEntry(Node *base,int id) {
if (base == nullptr){
return "";
}
if (base->id == id){
cout<<base->data<<endl;
return base->data;
}
getEntry(base->left,id);
getEntry(base->right,id);
}
below are the nodes I passed in from main:
int main(){
BST *newBst = new BST();
newBst->addNode(newBst,1);
newBst->addNode(newBst,2);
newBst->addNode(newBst,3);
newBst->addNode(newBst,2);
newBst->addNode(newBst,3);
newBst->addNode(newBst,5);
newBst->addNode(newBst,7);
newBst->addNode(newBst,10);
cout<<newBst->getEntry(newBst,5)<<endl;
return 0;
}
The code would compile but does not return anything, I tried to debug, at the "return base->data statement", there is an error "can not access memory at address 0xc8". What causes the problem and what can I do about it?
this is the warning I got when I debug the code.
if (base->id != id){
getEntry(base->left,id);
getEntry(base->right,id);
}
As you are using a sorted tree, you know which of the right or left node you need to have a look at. Also, you need to return something:
if (base->id > val){
return getEntry(base->left,id);
}
return getEntry(base->right,id);
But the design with addNode is very bad, you shouldn't have to pass the root twice!
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;
}