I'm writing a simple Binary Tree program in C++ and right now it only stores the most recent value entered at the root node eg. if I enter 10 into the tree then 9 into the tree, 9 just overwrites 10 as the root node so the tree only stores the value 9.
I've looked at multiple C++ Binary Tree solutions online and tried their version of implementing them yet I still get no success.
Here is my struct for a single node in the tree
struct TreeNode{
int value;
TreeNode *left;
TreeNode *right;
TreeNode(int value){
this -> value = value;
left = NULL;
right = NULL;
}
};
My class for the binary tree so far
class IntTree{
private :
TreeNode *root;
public :
IntTree();
TreeNode* getRoot();
void insertValue(TreeNode *root, int intValue);
TreeNode* searchTree(TreeNode *root, int intValue);
void inOrder(TreeNode *root);
void deleteValue(int intValue);
void deleteTree(TreeNode *root);
};
The Insert Method
void IntTree::insertValue(TreeNode *root, int intValue){
if(root == NULL){
root = new TreeNode(intValue);
}
else if(intValue == root->value){
cout << "Value already exists in the tree" << endl;
}
else if(intValue < root->value){
insertValue(root->left, intValue);
}
else{
insertValue(root->right, intValue);
}
}
And then this method is simply called in a menu like this
cout << "Enter Value to Insert : " << endl;
input = readInt();
theTree.insertValue(theTree.getRoot(), input);
The logic all seems fine to me, apart from that I've tried not using a constructor and just induvidually setting the variable, having two functions for inserting one with just the int parameter which so I don't have to use the getRoot() later on and a million other things which I've forgotten
The answer is simple, the pointer you are modifying is only a copy, so the copy is discarded at the end of the function and you have lost memory. You need to take a reference on the pointer to actually modify it (nothing else to modify):
void insertValue(TreeNode *& root, int intValue)
This should work:
New insertvalue function call will look as below
void insertValue(TreeNode **root, int intValue)
{
if(*root == NULL)
{
*root = newNode(intValue);
}
else if(intValue == (*root)->value)
{
cout << "Value already exists in the tree" << endl;
}
else if(intValue < (*root)->value)
{
insertValue(&(*(root))->left, intValue);
}
else
{
insertValue(&(*(root))->right, intValue);
}
}
int main()
{
//initial code
insertvalue(&root,value) //root is a single pointer variable.
//code for printing the tree
}
There are many less complex ways to implement the same. i have just modified your code.
Related
I'm trying to make a binary search tree based on an array of integers.
I've created a function BST that takes an array and its size as a parameter. Now I'm calling another function makeBST on every item of the array that takes the root node and that value. It creates another node and attach it with the root node based on the value.
But the makeBST function is not recursing over itself and executing the NULL condition for every value of the array, even though root node is not null
#include<iostream>
#include<cmath>
using namespace std;
class Node {
public:
int data;
Node *left;
Node *right;
};
Node *newNode(int x){
Node *node = new Node();
node->data = x;
node->left=NULL;
node->right = NULL;
return node;
};
void makeBST(Node *node, int x){
if(node==NULL){
// keep getting executed even though root node has a value.
// here must be error.
cout << " NULL condition " << endl;
node = newNode(x);
return;
};
if((node->data) > x){
cout << "also working" << endl;
makeBST(node->left,x);
}else if((node->data) < x){
makeBST(node->right,x);
};
};
Node *BST(int arr[], int n){
Node *root = newNode(arr[0]);
for(int i=1; i<=n-1; i++){
cout << "loop" << i << endl;
makeBST(root,arr[i]);
};
return root;
};
int main(){
int arr[10] = {1,2,3,4,5,6,7,8,9,10};
int n=10;
Node *root = BST(arr,n);
return 0;
};
I know this is not the best way of creating Binary search tree. But I'm a beginner and this is what i could come up with.
Can anyone help?
currently, you are changing the local value for (*node) in the function without have any effect on the variable node passing to it. You should read about passing pointers as value vs. as reference.
If you want to change node you need to pass it as reference:
void makeBST(Node **node, int x) {
if(*node==NULL){
cout << " NULL condition " << endl;
node = &newNode(x);
return;
};
if((*node->data) > x){
cout << "also working" << endl;
makeBST(&(*node->left),x);
}else if((*node->data) < x){
makeBST(&(*node->right),x);
};
};
Make sure you pass the address of the node when calling makeBST.
I am implementing a number of LinkedList ADT's for my compsci class and I'm running into the same problem on every one. The code listed below is a binary tree ADT. The compiler gets lost when trying to input data into the new nodes. The code compiles without any errors, but the compiler does not return anything, I think it's stuck trying to find the pointer. I come from Java so I'm still working my way around pointers.
#include <iostream>
struct TreeNode {
//represents a single node in a binary tree of int data
int data; //immediate data
TreeNode *left; //left subtree
TreeNode *right; //right subtree
TreeNode(int in);
};
TreeNode::TreeNode(int in) {
data = in;
left = NULL;
right = NULL;
}
The compiler can't seem to find the pointer referenced in these two append functions.
void addLeft(TreeNode *root, int newData) {
TreeNode *new_node;
new_node->data = newData;
root->left = new_node;
}
void addRight(TreeNode *root, int newData) {
TreeNode *new_node;
new_node->data = newData;
root->right = new_node;
}
//counts nodes in binary tree from designated root point
int countNodes(TreeNode *root) {
if (!root) {
return 0; //empty tree
}
int count = 1;
count += countNodes(root->left); //adds left subtree nodes
count += countNodes(root->right); //adds right subtree countNodes
return count;
}
void preorderPrint(TreeNode *root) { //root first, then left, then right
if (root) {
std::cout << root->data << " ";
preorderPrint(root->left);
preorderPrint(root->right);
}
}
void postorderPrint(TreeNode *root) { //left first, then right, then root
if (root) {
postorderPrint(root->left);
postorderPrint(root->right);
std::cout << root->data << " ";
}
}
void inorderPrint(TreeNode *root) { //left first, then root, then right
if (root) {
inorderPrint(root->left);
std::cout << root->data << " ";
inorderPrint(root->right);
}
}
bool tree_contains(TreeNode *root, int item) {
if (!root) {
return false; //if the root doesn't exist, the tree doesn't exist
}
else if (root->data = item) {
return true; //item is found in the root node
}
else if (root->data > item) {
}
}
int main() {
TreeNode *root;
root->data = 5;
addLeft(root, 4);
addRight(root,9);
inorderPrint(root);
return 0;
}
Your root is not initialized. It currently has an undefined value. It should be:
TreeNode *root = new TreeNode(5);
... // Do whatever you want
// delete root and everything else.
A pointer is just a variable that holds an address of an object in memory. When you define a pointer like
int *foo;
you haven't initialized it, so its value is indeterminate. That means it doesn't hold a valid pointer value that could be used to access an object in memory. To make a pointer actually point to something, you have to assign it an address:
int bar;
inf *foo = &bar;
Now foo holds the address of bar and you can dereference foo to write to bar:
*foo = 42;
// bar is now 42
In your code
TreeNode *root;
root->data = 5;
You try to dereference (root->data is just syntactic sugar for (*root).data) a pointer root that hasn't been initialized with or assigned a valid pointer value.
Since you want to create a dynamic data structure that grows on demand, you want to allocate memory at runtime. You could do so using the new operator:
TreeNode *root = new TreeNode; // allocates an object of the type
// TreeNode
root->data = 5; // is now safe.
But since you provide a constructor for TreeNode that takes an int you can write:
TreeNode *root = new TreeNode{ 5 };
The same goes for many other locations in your code as well.
Please remember that dynamically allocated memory should be deallocated when it is no longer needed:
`delete root;`
So i'm making a simple binary tree to store integers but I keep getting a "expression must have pointer-to-class type" error in the insert function, this is probably just me not noticing something obvious but I'm relatively new to C++ so any help would be appreciated. Thanks
struct node
{
//Data stored in this node of the tree
int data;
//The left branch of the tree
node *left;
//The right branch of the tree
node *right;
};
using namespace std;
//Inserts a value into the tree
void insert(node **tree, int value)
{
if (*tree == nullptr)
{
//Create new node
*tree = new node;
//Set new value
(*tree)->data = value;
//Set branches to nullptr
(*tree)->left = nullptr;
(*tree)->right = nullptr;
}
else
{
if (value < (*tree)->data)
insert(*tree->left, value);//ERROR HERE
if (value >(*tree)->data)
insert(*tree->right, value);//ERROR HERE
}
}
//Deletes the tree
void delete_tree(node *tree)
{
if (tree != NULL)
{
delete_tree(tree->left);
delete_tree(tree->right);
delete tree;
}
}
//Prints the tree in order
void inorder(node *tree)
{
if (tree != nullptr)
{
inorder(tree->left);
cout << tree->data << " ";
inorder(tree->right);
}
}
int main(int argc, char **argv)
{
while (true){
//if(userinputflag=0)
//else node *tree = input number
node *tree = nullptr;
while (true)
{
int num;
cout << "Enter number (-1 to exit): ";
cin >> num;
if (num == -1)
break;
insert(&tree, num);
}
inorder(tree);
cout << endl;
}
}
The signature of insert is:
void insert(node **tree, int value);
You are passing in *tree->left, which is *(tree->left), which is not a valid expression because tree is not a "pointer-to-class type", as the error suggests (it's a pointer-to-pointer-to-class).
What you had intended was (*tree)->left, which is a valid expression, but that would be a node* and our signature calls for a node**, hence:
insert(&((*tree)->left), value);
insert(*tree->left, value)
Operator -> has a higher precedence than *. The expression tree->left is syntactically wrong as tree type in the expression is node **. So, try -
insert(&((*tree)->left), value)
You function as first parameter requier pointer-to-pointer to node
void insert(node **tree, int value)
And here
insert(*tree->left, value);//ERROR HERE
which is not a valid.
I think you need something like this
insert(&((*tree)->left), value);//ERROR HERE
This is my first time working with trees. I wrote a c++ code, but it says Segmentation fault (core dumped) , As far as I searched, this error comes from accessing a memory location that may be NULL. I tried 'new' keyword as malloc() should be avoided in c++, But still I didn't get how to resolve this in my code.
# include<iostream>
using namespace std;
struct node
{
int data;
node *left;
node *right;
}*next;
int k=0;
void tree(int i,/*struct*/ node *next = new node)
{
++k; --i;
if (i==0)
return;
//next = new node;
next->data = k*k;
next->left = NULL;
next->right = NULL;
tree(i, next->left);
tree(i, next->right);
return ;
}
void display (node* next)
{
cout<<next->data<<" ";
if (next->left!=NULL)
{
display(next->left);
display(next->right);
}
}
int main()
{
int h;
cout<<"Enter the expected height of tree : ";
cin>>h;
node *root;
root = new node;
root->data=0;
root->left=NULL;
root->right=NULL;
tree(h, (root->left));
tree(h, (root->right));
cout<<root->data<<" ";
display(root->left);
display(root->right);
return 0;
}
There are serious problems with this code. In particular, here:
void display (node* next)
{
cout<<next->data<<" ";
if (next->left!=NULL)
{
...
}
}
You dereference next without ever checking to see whether it's null. And it will be null. That's enough to explain the error you see.
I say that it will be null because of this:
void tree(int i,/*struct*/ node *next = new node)
{
...
return ;
}
...
root->left=NULL;
...
tree(h, (root->left));
...
display(root->left);
The tree function takes its second argument by value-- that means that it does not change the value of root->left. You then call display with a null argument. I suspect that you think void tree(int i,/*struct*/ node *next = new node) means something other than what it actually means.
More fundamentally, you must review the two ways to pass an argument, by reference and by value.
More fundamentally still, you must start with a small, simple program and build up in small steps, rather than trying to write a big complex program all at once.
#include <iostream>
using namespace std;
struct node
{
int data;
struct node *left;
struct node *right;
};
void tree(int i, struct node **root, int k)
{
if (i < 1)
return;
*root = new struct node;
(*root)->data = k*k;
(*root)->left = NULL;
(*root)->right = NULL;
tree(i - 1, &((*root)->left), k + 1);
tree(i - 1, &((*root)->right), k + 1);
}
void display(struct node *root)
{
if (root == NULL)
return;
cout << root->data << " ";
if (root->left != NULL)
display(root->left);
if (root->right != NULL)
display(root->right);
}
int main()
{
struct node *root;
int h;
cout<<"Enter the expected height of tree : ";
cin>>h;
tree(h, &root, 0);
display(root);
return 0;
}
I think you should do some more read up on how pointers works: http://www.tutorialspoint.com/cprogramming/c_pointers.htm
When you where calling tree(h, root->left) you actually just send the pointers value "NULL" == 0x0. As you want to allocate memory for it you should send a reference to the pointer. Hence &root and &((*root)->left). In the display function you have to check for NULL values both for left and right.
The code above is only improved and doesn't handle any freeing of memory, to be able to do that, traverse the tree and use delete on all leafs and work you back to the root.
Just a simple BST to print numbers inorder. Couldn't figure out what I did wrong.
#include <iostream>
using namespace std;
class bst {
private:
bst* root;
bst* left;
bst* right;
int value;
public:
bst(const int& numb) : root(NULL), left(NULL), right(NULL) {
value = numb;
}
void insert(const int& numb) {
if (numb < value) {
if (left == NULL) {
left = new bst(numb);
left->root = left;
} else {
left->insert(numb);
}
} else if (numb > value) {
if (right == NULL) {
right = new bst(numb);
right->root = right;
} else {
left->insert(numb);
}
} else if (numb == value) {
cout << "duplicated value" << endl;
}
}
void inorder() {
if (left == NULL) cout << value << endl;
else left->inorder();
right->inorder();
}
};
int main() {
bst tree(5);
tree.insert(7);
tree.insert(1);
tree.insert(3);
tree.insert(2);
tree.insert(9);
tree.insert(10);
return 0;
}
Line 29 should read:
right->insert(numb);
where it currently reads:
left->insert(numb);
I highly recommend looking into gdb for solving situations like this.
inorder() should be:
if (left != NULL) left->inorder();
cout << value << endl;
if (right != NULL) right->inorder();
I assume the rest are correct.
Logic errors throughout.
Crash is here:
if (right == NULL) {
right = new bst(numb);
right->root = right;
} else {
left->insert(numb);
}
The else case shold use right, not left.
At least as I see it, your fundamental design is flawed. Although I realize many text books (and such) describe a tree as a recursive structure where each node has two sub-trees, I've never found that a very good way to design the code.
At least in my experience, in actual code, you're (much) better off separating the notion of a node in the tree from the notion of an entire tree. Only the tree should be visible to the outside world; node should be hidden away inside the tree, invisible to the outside world.
class bst {
class node {
int value;
node *left;
node *right;
// ...
};
// ...
node *root;
};
I'd then split insert into two pieces: a public function that takes a value, and just forwards to the second function with the root as the starting point. The second actually traverses the three and inserts the new item:
// public interface:
void insert(int v) {
insert(new node(v), root);
}
// private workhorse:
void insert(node *n, node *&pos) {
if (pos == NULL)
pos = n;
else if (n->value < pos->value)
insert(n,pos->left);
else if (n->value > pos->value)
insert(n,pos->right);
else
// duplicate value.
}
Likewise, inorder gets split into a public and private pair, with the public providing only an interface, and the private one doing all the real work:
// public interface:
void inorder() {
inorder(root);
}
// private worker
void inorder(node *n) {
if (n==NULL)
return;
inorder(n->left);
std::cout << n->value << endl;
inorder(n->right);
}
For what it's worth: yes, I have tested this code and it does work at least with the input you used in you main. It does have shortcomings though. For example, both insert and inorder traverse the tree recursively, so a large, badly imbalanced tree could lead to stack overflow. It's fairly easy to do insertion iteratively, but for real use you usually just switch to some sort of balanced tree instead.