I am currently using VS2015 for this.
I am trying to create a binary search tree in c++ so that I can learn both the language and the data structure while trying to see if I can follow good practices. However, I am coming through a problem where I am not properly instantiating the object properly in the driver file.
BSTHeader.h
#pragma once
/*
Properties of Binary Search Tree:
1.) Elements less than root will go to the left child of root
2.) Elements greater than root will go to the right child of root
*/
#include <memory>
// Binary Search Tree handler class
class BSTHeader {
/*
Naive implementation of BSTNode (non-generic version)
Nested class is private, but it's internal fields and member functions
are public to outer class: BSTHeader
*/
class BSTNode {
public:
int data;
std::unique_ptr<BSTNode> left;
std::unique_ptr<BSTNode> right;
BSTNode(int val) {
data = val;
left = NULL;
right = NULL;
}
~BSTNode() {}
};
std::unique_ptr<BSTNode> root; // Root of BST
unsigned int size; // Total amount of nodes in tree from root
public:
BSTHeader();
BSTHeader(int val);
~BSTHeader();
bool insert(std::unique_ptr<BSTNode>& root, int val);
}
BSTHeader.cpp
#include "BSTHeader.h"
/*
Constructors:
*/
BSTHeader::BSTHeader() {
root = NULL;
size = 0;
}
BSTHeader::BSTHeader(int val) {
root = std::unique_ptr<BSTNode>(new BSTHeader::BSTNode(val)); // Smart pointer to an internal BSTNode
size = 1;
}
BSTHeader::~BSTHeader() {} // Empty destructor from use of smart pointer
/*
Member functions:
*/
bool BSTHeader::insert(std::unique_ptr<BSTNode>& root, int val) {
if (root == NULL) { // Place new element here
root = std::unique_ptr<BSTNode>(new BSTHeader::BSTNode(val));
size++;
return true;
}
if (val < root.get()->data) { // val < root
insert(root.get()->left, val);
}
else if (val > root.get()->data) { // val > root
insert(root.get()->right, val);
}
The issue I get is here, where I believe I am trying to instantiate a BSTHeader object.
Program.cpp
#include "BSTHeader.h"
int main()
{
BSTHeader::BSTHeader bst(); // <----- ERROR
return 0;
}
The error I am getting is cannot determine which instance of overloaded function "BSTHeader:BSTHeader" is intended
However, whenever I do:
BSTHeader bst()
I am not able to access the insert(..., ...) function for the object doing bst.insert(..., ...) due to expression must have class type even though the error above does not appear.
Yet everything works fine and I am able to access all the member methods by doing this: BSTHeader bst(5) by using the overloaded constructor.
I am not sure whether its a namespace issue or not. I feel as though I am missing something.
The line
BSTHeader::BSTHeader bst(); // <----- ERROR
is a declaration of a function named bst that takes no arguments and returns a BSTHeader::BSTHeader.
This is known as the "most vexing parse", and often described in less polite language.
If you want to instantiate an instance, giving the constructor no arguments, remove the ().
Related
I have made a superclass named "tree". I have constructed the tree in this class. Now, I want to pass the root of the constructed tree to another class which is a subclass of tree. But when I try to pass it, the subclass calls the supercalss constructor and sets it to NULL;
struct node
{
struct node *left;
struct node *right;
int val;
};
struct node *create(int val)
{
struct node *temp = (struct node *)malloc(sizeof(struct node));
temp->val = val;
temp->left = temp->right = NULL;
return temp;
};
class tree
{
public:
struct node *root;
tree()
{
root = NULL;
}
void createtree()
{
root = create(5);
}
void preorder()
{
preorderp(root);
}
void preorderp(struct node *p)
{
if(!p) {
return;
}
cout<<p->val<<' ';
preorderp(p->left);
preorderp(p->right);
}
};
This is the definition of my tree class. It just creates a tree with one node having value 5. Now I want to pass the new root created to a subclass of tree.
class treeiterator:public tree
{
struct node *p;
stack<struct node *> s;
public:
treeiterator()
{
p = root;
push(root);
}
bool hasnext();
int next();
private:
void push(struct node *root);
};
I create an object for tree first and then do createtree. Now, when I create an object for treeiterator, it's member p gets sets to NULL since supercalss constructor is also called. How can I just access the tree created in the superclass in subclass?
Full code:
#include <bits/stdc++.h>
using namespace std;
struct node
{
struct node *left;
struct node *right;
int val;
};
struct node *create(int val)
{
struct node *temp = (struct node *)malloc(sizeof(struct node));
temp->val = val;
temp->left = temp->right = NULL;
return temp;
};
class tree
{
public:
struct node *root;
tree()
{
root = NULL;
}
void createtree()
{
root = create(5);
}
void preorder()
{
preorderp(root);
}
void preorderp(struct node *p)
{
if(!p) {
return;
}
cout<<p->val<<' ';
preorderp(p->left);
preorderp(p->right);
}
};
class treeiterator:public tree
{
struct node *p;
stack<struct node *> s;
public:
treeiterator()
{
p = root;
push(root);
}
bool hasnext();
int next();
private:
void push(struct node *root);
};
void treeiterator::push(struct node *t)
{
while(t) {
s.push(t);
t = t->left;
}
}
bool treeiterator::hasnext()
{
return s.empty()?1:0;
}
int treeiterator::next()
{
struct node *t = s.top();
int val = t->val;
s.pop();
if(t->right) {
push(t->right);
}
return val;
}
int main()
{
tree t;
t.createtree();
t.preorder();
treeiterator it;
while(it.hasnext()) {
cout<<it.next()<<' ';
}
}
Because of inheritance every treeiterator is also a tree. This means
treeiterator treeIt;
treeIt.createtree();
will do what OP wants. There is no need to make a separate tree and moving the root around.
However this is a bit odd in the world of C++ because OP is under-using the constructor. For example, node could be:
struct node
{
node *left;
node *right;
int val;
node(int inval):
val(inval),
left(nullptr),
right(nullptr)
// the above is a Member Initializer List. It makes sure all of your
// members are initialized before the body of the constructor runs.
{
}
};
That bit after the : in the constructor is the Member Initializer List.
Now when you allocate a node it's initialized and ready to be linked. For tree
class tree
{
public:
struct node *root; // almost certainly should not be public.
// also should be a std::unique_ptr<node>
tree(int inval)
{
root = new node(5); // note new in place of malloc. new allocates
// storage and calls constructors. malloc should
// only be used in C++ in rare edge-cases.
}
/* obsolete
void createtree()
{
root = create(5);
}
*/
...
};
tree is assigned a root on allocation. treeiterator is a wee bit trickier because it must call tree's constructor to set up root.
class treeiterator:public tree
{
struct node *p; // Don't see the point off this
stack<struct node *> s; // or this, but that's another question
public:
treeiterator(int inval):
tree(inval) // call's tree's constructor
{
}
bool hasnext();
int next();
private:
void push(struct node *root);
};
Allocating a treeiterator now guarantees that it is all ready to go with no further work.
treeiterator treeIt(5); // all done.
All of the above is covered within the first few chapters of any good C++ programming text. I recommend getting one and reading it, because right now it looks like you are trying to write bad C.
Off topic 1:
You are going to quickly find that this code is in violation of the Rule Of Three. What is The Rule of Three? If you don't know, read the link. It will save you much time and hair-pulling
Off Topic 2:
#include <bits/stdc++.h>
using namespace std;
Is a ticking time bomb. The first line includes the entire standard library, but only in GCC. Your code is now doing far, far more work than it need to to compile, is no longer standard C++, and is not portable to other compilers and may well break with the next revision of GCC. Don't use anything in bits. It internal compiler-specific stuff with no guarantees what-so-ever.
More here: Why should I not #include <bits/stdc++.h>?
The second line takes everything in the std namespace and places it in the global namespace. This leads to fun games like is reverse or std::reverse being called? Often this leads to insane and arcane compiler messages because the poor compiler is confused as hell, but sometimes it's not confused and picks the best choice among the many and silently breaks something else. Great fun debugging.
More here: Why is "using namespace std" considered bad practice?
Together you have the entire standard library pulled into your file AND stripped of it's proper namespace. This results in a vast minefield of potential hidden pain that is not worth any perceived time savings. One of the resulting bugs could cost more clean up than years of typing a few extra lines per file and characters.
No one want to clean up code with this stupid a mistake, so doing this in a professional setting can be costly.
First, you should not have root has public. This is a gross OO error. If you want it to be available to subclasses you should make it protected.
I have the following class declaration (I've tried to remove as much excess code as possible):
class List {
public:
struct Node {
int value;
};
Node * findNode(unsigned int) {
return new Node;
}
};
This gives no error. However, as soon as I define the function "findNode" outside of the class, I get an error; here's the code:
class List {
public:
struct Node {
int value;
};
Node * findNode(unsigned int);
};
Node * List::findNode(unsigned int index) {
return new Node;
}
Now, when running the code, I get an error saying "LinkedList.cpp:9:1: error: 'Node' does not name a type".
I would appreciate any help in determining the problem.
Until the compiler encounters List:: it has no idea the Node you're talking about is a member of List. Change the definition to:
List::Node * List::findNode(unsigned int index) {
return new Node;
}
The "naked" Node inside the function is fine because by that time the compiler knows the function is a member of List.
The method Minimum returns the minimum element in the binary search tree. If no argument is passed it prints the minimum of calling object. If address of a node is passed it prints the minimum of the subtree whose root is node
When compiled it shows "Invalid use of non static data member Tree::root"
#include<stdlib.h>
#include<iostream>
class Node
{
public:
Node *leftchild;
Node *rightchild;
Node *parent;
int info;
};
class Tree
{
public:
Node *root;
Tree()
{
root=NULL;
}
void Minimum(Node*);
};
void Tree::Minimum(Node *curnode=root)
{
Node *parent;
while(curnode!=NULL)
{
parent=curnode;
curnode=curnode->leftchild;
}
std::cout<<parent->info<<endl;
}
int main()
{
Tree tree;
tree.Minimum();
return 0;
}
No, you cannot.
For the default value you can use either a value, a variable or a function that is accessible in the context of the function definition that is, in the class definition, which is outside of any particular object's context.
It usually helps me thinking on how the compiler really processes this. In particular, when the compiler does overload resolution for a function and finds an overload that has more arguments than those used at the place of call, the compiler will generate code at the place of call to fill in the rest of the arguments. The generated code will always generate a call with all of the arguments:
int g();
void f(int x = g());
int main() {
f(); // [1]
}
When the compiler processes [1] and it does overload resolution it finds that void ::f(int x = g()) is the best candidate and picks it up. It then fills the default argument and generates the call for you:
int main() {
f( /*compiler injected*/g() );
}
If you consider a call to a member function, or a member variable of the class, it would not make sense in the context of the caller (the language could be changed to adapt to this, it is not impossible to handle that, but with the current model it does not work).
You can alternatively set it to NULL for example as default, and then check and set it to the member in the method.
Or overload the method with void Minimum(); and in that method call the one with an argument with the member.
void Tree::Minimum() {
Minimum(root);
}
I couldn't find any way to get the default parameter to work like that. But you can get the same result by overloading the function, like so:
class Tree
{
public:
Node *root;
Tree()
{
root=NULL;
}
void Minimum(Node*);
void Minimum();
};
void Tree::Minimum(Node *curnode)
{
Node *parent;
while(curnode!=NULL)
{
parent=curnode;
curnode=curnode->leftchild;
}
std::cout<<parent->info<<std::endl;
}
void Tree::Minimum()
{
Minimum(root);
}
If the case where an argument of NULL is explicitly passed doesn't need to be differentiated from no argument being passed, you could set NULL as the default and use root if curnode is NULL.
void Tree::Minimum(Node *curnode=NULL)
{
if (curnode==NULL)
curnode = root;
Node *parent;
while(curnode!=NULL)
{
parent=curnode;
curnode=curnode->leftchild;
}
std::cout<<parent->info<<endl;
}
Im implementing a B+Tree for a class. The Nodes are currently implemented like this:
class Node {
public:
E* keys[order*2];
Node *children[order*2+1];
int size;
Node(){
size = 0;
}
bool empty() {
return size == 0;
}
bool isLeafNode() {
return false;
}
};
class LeafNode : public Node {
public:
E* data[order*2+1];
bool isLeafNode() {
return true;
}
};
When I want to add an element to a leaf node (by accessing LeafNode->data), I get
error: request for member ‘data’ in ‘left<int>’, which is of non-class type ‘BTree<int>::LeafNode*()’
I guess this happens because the compiler doesn't know whether the Node I'm accessing is an inner- or leaf-node, although I'm checking it first by using isLeafNode().
I can't merge the two classes into one, because the Leaf Nodes need one more Bucket for the data than the inner nodes.
I realize this is sort of a design-question, but is there some trivial approach to this problem that I'm missing? I'm fairly new to C++.
You really should use a virtual method for something like this. You can change your isLeafNode() query to return a pointer to the leaf node if it is one, and NULL otherwise.
class LeafNode; // forward declare
class Node {
//...
public:
virtual ~Node () {}
virtual LeafNode * isLeafNode () { return 0; }
//...
};
class LeafNode : public Node {
//...
public:
LeafNode * isLeafNode () { return this; }
//...
};
Then, you can use this method from a Node to access the data if it is actually a LeafNode.
The error message
error: request for member ‘data’ in ‘left<int>’, which is of non-class type ‘BTree<int>::LeafNode*()’
and other errors of this form usually mean that you are trying to access a field of a struct using a . when you should be using ->. For example, if you have
LeafNode* ptr = /* ... */;
ptr.data[0] = /* ... */;
You will get an error on the second line, because you are using . instead of ->.
Try seeing if this is the error you're having on the indicating line and, if so, change the dot to an arrow.
Hope this helps!
I'm making a B inary S earch T ree (BST for short) and I've run into a problem that I can't figure out.
I shall try and reduce the amount of code but it still may require quite a bit I'm afraid.
Nodes:
template <typename Type>
class BSTNode { // Binary Search Tree nodes
private:
int key; // we search by key, no matter what type of data we have
Type data;
BSTNode *left;
BSTNode *right;
public:
BSTNode (int, Type);
bool add (int, Type);
Type search (int);
BSTNode<Type> *remove (int, BSTNode*);
BSTNode<Type> *minNode (int);
};
Root:
template <typename Type>
class BST { // The binary search tree containing nodes
private:
BSTNode<Type> *root; // Has reference to root node
public:
BST ();
bool add (int, Type);
Type search (int);
bool remove (int);
};
I don't know how much code to give since I don't want to exaggerate, if you need more, say so please.
I do both do recursive search and remove
template<typename Type>
BSTNode<Type> *BSTNode<Type>::remove(int removeKey, BSTNode *parent) {
// Here I try to remove nodes
// Depending on the number of children a node has, I remove in different ways
// The error occurs at removing a node with 2 children
// here I look for smallest node greater than current node, replace current node, delete node I replaced WITH
if (this->left != NULL && this->right != NULL){
int *auxKey = &key;
this = this->right->minNode(auxKey); // replace
return this->right->remove(this->key, this); // remove old node
}
}
Here is minNode:
template<typename Type>
Type *BSTNode<Type>::minNode (int oldKey) {
if (this->left == NULL) {
//oldKey = this->key;
return this->data;
} else
return left->minNode();
}
This is where the error occurs:
this = right->minNode(auxKey);
This causes a chain of errors, but I think the main error is:
error: invalid conversion from 'int*' to 'int' [-fpermissive]
I'm guessing it's something simple I've overlooked, but I just can't find it, have been trying for quite some time.
EDIT: Decided for now to simply pass key to minNode() and ignore oldKey and auxKey, modified minNode to return pointer.
New Error, same place
lvalue required as left operand
Your minNode function takes in an int value representing the old key, but you're passing an int* into it in the remove function (specifically, auxKey). Try passing in the value of the old key, not a pointer to it. Alternatively, if you want to update the in parameter to hold the correct value (you seem to be trying to do this), change the parameter to a reference parameter.
Hope this helps!