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
Related
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'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.
description
I don't know how to do this task.... but i just created a tree and enter value..can anyone please help me to do this task...the Stack is also of node type and we have to push value of operators like ab+ so we will push a as node then b as node and when + will come we make a tree and a and b will be its leafs node.
.Code
#include<iostream>
using namespace std;
class Node{
public:
int data;
Node *left;
Node *right;
Node()
{
data = 0;
left = NULL;
right = NULL;
}
};
class Tree
{
Node *root;
void insert(int d, Node *node)
{
if (d < node->data)
{
if (node->left == NULL)
{
Node *leaf = new Node();
leaf->data = d;
node->left = leaf;
}
else
{
insert(d, node->left);
}
}
else
{
if (node->right == NULL)
{
Node *leaf = new Node();
leaf->data = d;
node->right = leaf;
}
else
{
insert(d, node->right);
}
}
}
void inOrderDisplay(Node *subRoot)
{
if (subRoot != NULL)
{
inOrderDisplay(subRoot->left);
cout << subRoot->data << " ";
inOrderDisplay(subRoot->right);
}
}
void postOrderDisplay(Node *subRoot)
{
if (subRoot != NULL)
{
postOrderDisplay(subRoot->left);
postOrderDisplay(subRoot->right);
cout << subRoot->data << " ";
}
}
void preOrderDisplay(Node *subRoot)
{
if (subRoot != NULL)
{
cout << subRoot->data << " ";
preOrderDisplay(subRoot->left);
preOrderDisplay(subRoot->right);
}
}
void deleteSubtree(Node *subRoot)
{
if (subRoot != NULL)
{
deleteSubtree(subRoot->left);
deleteSubtree(subRoot->right);
cout << "\ndeleting: " << subRoot->data;
delete subRoot;
subRoot = NULL;
}
}
public:
Tree()
{
root = NULL;
}
~Tree()
{
deleteAll();
}
void insert(int d)
{
if (root == NULL)
{
Node *leaf = new Node();
leaf->data = d;
root = leaf;
}
else
{
insert(d, root);
}
}
void inOrderDisplay()
{
inOrderDisplay(root);
}
void postOrderDisplay()
{
postOrderDisplay(root);
}
void preOrderDisplay()
{
preOrderDisplay(root);
}
void deleteAll()
{
deleteSubtree(root);
}
};
.Main Class:
#include<iostream>
#include"task1.h"
using namespace std;
void main()
{
Tree tree;
tree.insert(10);
tree.insert(6);
tree.insert(14);
tree.insert(5);
tree.insert(8);
tree.insert(11);
tree.insert(18);
cout << endl;
system("pause");
//tree.deleteAll();
}
Based on the code you have here, you only have a void insert(int d, Node *node) function, no void insert(operator o, Node *node) function.
I think this shows that you missed an important point here. Every node in the tree can either be an integer (as you did) or an operator. In both cases, I'd call it a string. Every node that is not a leaf must be an operator, and all leafs must be integers (or strings that represents operators/integer in our case).
Then, iterating over your input, the first three item should result in something like:
+
/ \
a b
The next step would be to build more sub trees (not sure of the definition of the input you have), keep them in your stack and then construct more inner nodes of the tree.
So if the tree I showed above is called Tree(+) (for ease of use), and the initial stack was [a,b,+,c,d,e,*,*], then after one iteration you'll have [Tree(+),c,d,e,*,*] and you continue from there.
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.
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...