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!
Related
Trying to make a B inary S earch T ree (BST for short) using a template.
When I try to create a new instance of my BST I get an unexpected error. I hope the solution does not involve pointers since I would like to keep them at a minimum.
For now I have:
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);
};
And the Node type:
EDIT: When I cut out code to un-encumber text, I forgot the constructor, now it's been added
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);
};
EDIT2: Here is the actual constructor
template <typename Type>
BSTNode<Type>::BSTNode (int initKey, Type &initData) {
this->key = initKey;
this->data = initData;
this->left = NULL;
this->right = NULL;
}
I want to try and test if anything works / doesn't work
BSTNode<int> data = new BSTNode (key, 10);
And I get: Expected type specifier before BSTNode. I have no idea what I'm doing wrong, but one thing I do hope is I don't have to use data as a pointer.
BSTNode<int> data = new BSTNode<int> (key, 10);
Also does not work, seems it believes < int > is < & int> and it doesn't match
First, you need to fully specify the type on the RHS of the assignment, and, since you are instantiating a dynamically allocated node with new, the LHS should be a pointer:
BSTNode<int>* data = new BSTNode<int> (key, 10);
^ ^
If you don't need a node pointer, then use
BSTNode<int> data(key, 10);
Second, your BSTNode<T> class doesn't have a constructor taking an int and a Type, so you need to provide that too.
template <typename Type>
class BSTNode {
public:
BSTNode(int k, const Type& val) : key(k), data(val), left(0), right(0) { .... }
};
This is my first time working with any kind of tree. I created a tnode class for my tree and now I'm trying to create the class for the tree itself. However I've gotten a couple errors I can't figure out.
#ifndef Tree_Ntree_h
#define Tree_Ntree_h
// SIZE reprsents the max number of children a node can have
#define SIZE 10
// SEPERATE will allow the program to distinguish when a subtree no longer has children
#define SEPERATOR '#'
#include <iostream>
#include <fstream>
template <typename T>
class tnode{
public:
T value;
tnode *child[SIZE];
tnode() {};
tnode<T> *addChild(T data){
tnode*temp = new tnode;
temp -> value = data;
for (int i=0; i<SIZE; i++)
temp -> child[i] = NULL;
return temp;
}
};
template <typename T>
class Ntree{
private:
tnode<T> *root;
T data;
std::string filename;
public:
Ntree(){ root= NULL;}
Ntree( T data){ *root = data;}
inline T getRoot(){return root;}
My errors are in the last three lines.
In the last line of my code (getRoot), this is the error:
No viable conversion from 'tnode > *' to
'std::__1::basic_string'
In the second to last line and the third to last line (*root = data) (root = NULL) this is the error:
No viable overloaded '='
I don't understand why it is necessary to overload the = operator in this situation.
root is a tnode<T> * and getRoot is returning a T object. The compiler doesn't know how to convert one to the other. You probably just want to return root->value
However, you haven't allocated any space for root and it might be NULL, so you need to determine what to do when it is NULL.
In this line:
Ntree( T data){ *root = data;}
This time you are assigning a T to a tnode<T>, which the compiler doesn't know how to do. You also haven't allocated any memory for root. Instead you probably want todo something like:
Ntree( T data){ root = new T; root->value = data;}
Or better still have a tnode constructor that takes a value.
I have the following code snipped, which implements a Binary Search Tree with templates:
#include<iostream>
using namespace std;
template<typename T>
class Node{
public:
T data;
Node<T> *left;
Node<T> *right;
Node<T> *parent;
Node(T input_data=NULL){
data=input_data;
left=NULL;
right=NULL;
parent =NULL;
}
};
template<typename T>
class BinarySearchTree{
private:
long n;
Node<T> *root;
public:
BinarySearchTree(Node<T> *input_root=NULL, long input_size=0){
n=input_size;
root=input_root;
}
void insert(Node<T> *p=root, T data){
Node<T> *par=NULL;
while(p!=NULL){
par=p;
if(data <= p->data)
p=p->left;
else
p=p->right;
}
Node<T> *z=new Node<T>(data);
if(root==NULL){
root=z;
n=1;
return;
}
z->parent=par;
if(data<=par->data)
par->left=z;
else
par->right=z;
n+=1;
}
void inorder(Node<T> *p=root){
if(p){
inorder(p->left);
cout<<p->data<<" ";
inorder(p->right);
}
}
int main(){
BinarySearchTree<int> *t=new BinarySearchTree<int>();
t->insert(5);
t->insert(15);
t->insert(3);
t->insert(14);
t->insert(25);
t->insert(10);
t->inorder();
}
There's a compilation error on line 27, (i.e. Node *root;), and which reads: "Invalid use of non-static data member 'BinarySearchTree::root'". I think it has to do with the default arguments that I've included have in the functions 'insert' and 'inorder', because I don't get the error when I remove the default argument 'root'.
My question is, what is happening and how do I get around it? I would like to preserve the default argument of root if that's possible.
If it matters, I'm using a software called 'Quincy 2005' on Windows 8.1 to compile (for certain reasons).
A default value must be a literal, not a variable name.
Additionally, arguments with default values must come last in the argument list.
Rather use:
void insert(Node<T> *p, T data) { ... }
// overload with only one argument
void insert(T data)
{
insert(root, data)
}
In a line such as
void insert( Node<T>* p = root ,T data ) {...}
there are 2 errors.
Firstly ,you can only use default value for the arguments starting at the last parameter and backwards.
Since you didn't give data a default value ,this is an error (solution reorder parameters ,those without default must come first).
Secondly ,the value root is a member of this and there is no this at the point of declaration.
Solution if you need a default there use nullptr as the default and inside your function test for nullptr and if so use root instead.
template <class Type>
class Node
{
public:
Node ()
{
}
Node (Type x, Node* nd)
{
data = x;
next = nd;
}
Node (Type x)
{
data = x;
next = NULL;
}
~Node (void)
{
}
Node (const Node* & nd)
{
data = nd->data;
next = nd->next;
}
Node & Node::operator = (const Node* & nd)
{
data = nd->data;
next = nd->next;
}
T data;
Node* next;
};
Do I replace every Node* with
Node*<Type>
I tried replacing it and tried running something like
Node* temp = myq.head;
but it says argument list for class template "Node" is missing. I'm not really sure how to work with Templates when I need the Node class itself being part of it
Every declaration of Node will need a type in <>.
For
Node* temp = myq.head;
it depends on what myq.head is defined as. If it's defined as Node<int>* then temp also has to be defined as Node<int>* temp. You always have to have the <> with template objects.
If you wanted to have Node* without knowing the type, you could use inheritance. Have a templated TypedNode class that inherits from a non-template Node class. You would be able to pass all those TypeNode<> objects around with Node*, but you wouldn't be able to get the value of the nodes back out without knowing their type.
I don't recommend this but If you really want to make nodelists with mixed types you'll need to track the types by either
Include an enum type in the base class that defines the type stored in the node, and define typedNode for each class, setting the enum in it's constructor, or returning it from a virtual method.
RTTI, Run Time Type Information http://en.wikipedia.org/wiki/Run-time_type_information
I am getting this message with everything that has Node* (this declaration has no storage or type specifier). Could somebody help and please send me in the right direction?
template <typename type>
Node* Stack<type>::pop() {
Node* retNode; // the node to be return
if(tos == NULL) {
cerr << "*** Stack empty ***";
exit(1);
}
else {
retNode = tos; // store the location of tos
tos = tos->getLink(); // move to new tos
retNode->setLink(); // unlink the popped node from the stack
size -= 1;
}
return retNode;
}
I am sure it's dealing with Node* but I just can't figure out what.
Below are my declarations for the node class that are being used in my stack class. Let me know if you need my declarations for the stack class as well because I just cant see the problem.
template <typename type>
class Node<type>{
private:
type data;
Node *link;
public:
Node(type p_item, Node *p_link);
type getData() const;
Node* getLink() const;
void setData(type p_data);
void setLink(Node *node);
};
Node is a class template, so you cannot use Node or Node * as data types. You must add template arguments in angle brackets, e.g. Node<int> or Node<char> * etc.
In the specific example you gave, it seems the following would be appropriate:
template <typename type>
Node<type>* Stack<type>::pop() {
Node<type>* retNode;
/* ... */
return retNode;
}
I.e. the same type argument that is used for Stack should (probably) be used for Node as well.
Two further notes:
It seems odd that, while the Node template appears to implement internal data structures of your stack, Node<type> * pointers are returned by the pop function of the stack. It would seem more natural (and better encapsulation, and more intuitive for the users of your stack) to return type objects.
It also seems odd that the pop function calls exit (and thus brings the entire process to a halt) when the stack is empty. Perhaps returning nullptr, or a dummy object, or throwing an exception (or a similar strategy) would be more appropriate.