I am trying to implement a red black tree with the use of templates. For example, when inserting an item to the tree, the key and the item should both be generic types. Till now, I implemented a header file which consists of a struct and functions to be implemented. However, I don't know if I'm using templates the right way. Also, when I tried to implement the 'Insert' function, the IDE gives the error:
prototype for ‘void RedBlackTree::InsertKey(Item*&, Key*&)’ does not match any in class ‘RedBlackTree’ RedBlackTree.h
This is my header file:
#ifndef REDBLACKTREE_H_
#define REDBLACKTREE_H_
template <class Item, class Key>
class RedBlackTree
{
typedef enum
{
BLACK,
RED
}ColourNode;
typedef struct RBT
{
struct RBT *left;
struct RBT *right;
struct RBT *parent;
struct RBT *root;
ColourNode colour;
Item item;
Key key;
}RBTNode;
public:
~RedBlackTree(); // destructor
RedBlackTree(Item, Key); // default constructor
void InsertKey(Item, Key);
int InsertFixUp(Item, Key);
int RemoveKey(Item, Key);
int FindKey(Item, Key);
private:
RedBlackTree<Item, Key> *rootPointer;
RedBlackTree<Item, Key> *NILL_LEAF;
};
template <class Item, class Key>
void RedBlackTree<Item, Key>::InsertKey(Item *&T, Key *&z)
{
//node* nil=tree->nil;
//node* root=tree->root;
RBTNode *y;
RBTNode *x;
y=T->nil;
x=T->root;
while(x != T->nil)
{
y=x;
if((z->key)<(x->key))
x=x->left;
else
x=x->right;
}
y=z->parent;
if(y == T->nil)
z=T->root;
else
if((z->key)<(y->key))
z=y->left;
else
z=y->right;
z->left=T->nil;
z->right=T->nil;
z->colour=RED;
InsertFixUp(T,z);
}
#endif /* REDBLACKTREE_H_ */
Thanks in advance.
The problem is that the types of the arguments to InsertKey don't match the declaration. In the declaration the arguments are Item and Key, and in the implementation they are Item*& and Key*& (references to pointers). These need to match.
void InsertKey(Item, Key);
^^^^ ^^^
void RedBlackTree<Item, Key>::InsertKey(Item *&T, Key *&z)
^^^^^^^ ^^^^^^
You have to move the implementation of the function (the template) to the class definition.
template <class Item, class Key>
class RedBlackTree
{
//...
public:
~RedBlackTree(); // destructor
RedBlackTree(Item, Key); // default constructor
void InsertKey(Item *&T, Key *&z)
{
//...
}
//...
};
Related
is there a way to pass in an extra argument to my function pointer in BST? I am trying to use BST inOrder to get value from a map<string, int>. this BST will be storing the key of the map.
The map will act as a database that uses date + time as the key. each BST will be created to store the date+time of each year and saved into another map (bstMap) which holds all bst. bstMap will use the year as key.
BST inOrder with function ptr.
#ifndef BST_H
#define BST_H
#include<iostream>
using namespace std;
template <class T>
class Node.
{
public:
T m_key;
Node<T> *m_left;
Node<T> *m_right;
};
template <class T>
class BST
{
typedef void(*funcPtr)(T &);
public:
BST();
void Insert(T key);
void Delete();
void InOrder(void(*funcPtr)(T &)) const;
void PreOrder(void(*funcPtr)(T &)) const;
bool Search(T key);
T MaxValue();
bool IsEmpty() const {return m_root == nullptr;}
void DeleteTree();
private:
Node<T> *m_root;
protected:
Node<T> *Insert(Node<T>* node, T key);
Node<T> *Search(Node<T>* node, T key);
void InOrder(Node<T>* node, void (*funcPtr)(T &)) const;
void PreOrder(Node<T>* node, void (*funcPtr)(T &)) const;
void DeleteTree(Node<T>* node);
Node<T>* MaxValue(Node<T>* node);
};
template<class T>
BST<T>::BST(){
m_root = nullptr;
}
template<class T>
void BST<T>::InOrder(Node<T>* node, void(*funcPtr)(T &)) const
{
if (node != nullptr)
{
InOrder(node-> m_left, funcPtr); //recursive call for node left
funcPtr(node-> m_key);
InOrder(node->m_right, funcPtr);
}
}
template<class T>
void BST<T>::InOrder(void(*funcPtr)(T &)){
InOrder(m_root, funcPtr);
}
This line of code is called from main.cpp which pass the user input year into the map to return the bst which stores all relevant keys.
void GetData(string& year, map<string, BST<string>>& bstMap)
{
BST<string> bstKey = bstMap[year];
bstKey.InOrder(&GetTotal);
}
So here is where i am stuck..
void GetTotal(string& key) <- how do i reference my database map here?
{
cout<< key <<endl;
}
If you want to access variables outside of the BST template class (such as the map), then I advise changing your template to the following (assuming that m_root is a member variable of BST<T>, and that it is the root of tree):
template<class T, class Fn>
void BST<T>::InOrder(Fn funcPtr) const
{
InOrder(m_root, fn);
}
template<class T, class Fn>
void BST<T>::InOrder(Node<T>* node, Fn funcPtr) const
{
if (node)
{
InOrder(node-> m_left, funcPtr); //recursive call for node left
funcPtr(node-> m_key);
InOrder(node->m_right, funcPtr);
}
}
Then this way, you can pass a function object or lambda that knows about the map. In the case below, a lambda function is used:
void GetData(string& year, map<string, BST<string>>& bstMap)
{
BST<string> bstKey = bstMap[year];
bstKey.InOrder([&](std::string& key) { std::cout << bstMap[key] << "\n"; });
}
The above provides a lambda that captures the passed-in map parameter.
When trying to compile I get the error: Error C2280 'std::variant<Tree::Position<int>,Tree::Position<std::string>,Tree::Position<double>,Tree::Position<bool>>::variant(const std::variant<Tree::Position<int>,Tree::Position<std::string>,Tree::Position<double>,Tree::Position<bool>> &)': attempting to reference a deleted function
I have a Tree class with a template sub-class Position. When using the load function of the Tree class, an instance of the Position class is added to the Tree's treePositionList. Also in the constructor function of the Position class an instance of the Position class is added to its childenList. I think the problem is related to the adding of an instance to those lists, though I do not understand what goes wrong exactly.
template <typename E>
class Node {
private:
string column;
E element;
public:
Node(E el, string col) { element = el; column = col;}
};
class Tree {
public:
template <typename E>
class Position {
private:
typedef variant<Position<int>, Position<string>, Position<double>, Position<bool>> Position_ManyTypes;
typedef list<Position_ManyTypes> PositionList;
Node<E>* node;
PositionList childrenList;
public:
Position(Tree* tree, const E element, const string column, const Json::Value &children);
Position(Position<E>& position);
~Position();
Position<E>& operator=(const Position<E> &position);
friend class Tree;
};
typedef variant<Position<int>, Position<string>, Position<double>, Position<bool>> Position_ManyTypes;
typedef list<Position_ManyTypes> PositionList;
Tree() {}
bool load(string filename);
private:
PositionList treePositionList;
};
bool Tree::load(string filename) {
ifstream rules_file(filename, ifstream::in);
Json::Value rules;
rules_file >> rules;
rules_file.close();
Position<string> root_position = Position<string>(this, "string123", "string456", rules["children"]);
treePositionList.push_back(root_position);
return true;
}
template <typename E>
Tree::Position<E>::Position(Tree::Position<E>& position) {
node = position.node;
childrenList = position.childrenList;
}
template <typename E>
Tree::Position<E>& Tree::Position<E>::operator=(const Tree::Position<E>& position) {
if (this != &position) {
delete node;
node = position.node;
childrenList = position.childrenList;
}
return *this;
}
template <typename E>
Tree::Position<E>::~Position() {
delete node;
}
template <typename E>
Tree::Position<E>::Position(Tree* tree, const E el, const string col, const Json::Value &children) {
node = new Node<E>(el, col);
Position<string> pos = Position<string>(tree, "string123", "string456", children[0]["children"]);
childrenList.push_back(pos);
}
I am trying to do the add function in BSTree.However, I have no idea where to start. Can anyone give me some hints which part I need to consider first. I don't know where is the new Pair(key, value); to use and what is the using Tree::data;. I just want to get the hints but not the answer. Thank you.
Below is the Pair.h file
#ifndef PAIR_H_
#define PAIR_H_
//a key-value pair
//this simple class is pretty much self-explanatory
//all its implementation is already given
template<typename KeyType, typename ValueType>
class Pair
{
public:
Pair(KeyType k, ValueType v) :
key(k), value(v)
{
}
KeyType getKey() const
{
return key;
}
void setKey(KeyType key)
{
this->key = key;
}
ValueType getValue() const
{
return value;
}
void setValue(ValueType value)
{
this->value = value;
}
private:
KeyType key;
ValueType value;
};
#endif /* PAIR_H_ */
Below is the Tree.h
template<typename Container, typename KeyType, typename ValueType>
class Tree
{
public:
virtual bool add(KeyType key, ValueType value) = 0; //pure virtual function here, description can be found in BSTree class
virtual bool remove(KeyType key) = 0; //pure virtual function here, description can be found in BSTree class
virtual ValueType getValue(KeyType key) = 0; //pure virtual function here, description can be found in BSTree class
virtual ~Tree(){}; //an empty destructor
protected:
Container data; //the data container (a vector, which is either a ListVector or ArrayVector in this assignment)
//that stores all the node data of the tree
//how the node is stored in the data container is very specific
//please refer to the webpage description for details
//treeToString in Utility is this class's only friend... :(
template<typename aContainer, typename aKeyType, typename aValueType>
friend string treeToString(Tree<aContainer, aKeyType, aValueType>* tree);
};
#endif
Below is the BSTree.h file
#ifndef BSTREE_H_
#define BSTREE_H_
#include "Tree.h"
#include "Pair.h"
#include <typeinfo>
using namespace std;
//the Binary Search Tree class
//the keys have to be unique in the tree - you need to make sure of that when performing the insertion
template<typename Container, typename KeyType, typename ValueType>
class BSTree : public Tree<Container, KeyType, ValueType>
{
public:
BSTree(){};
~BSTree();
//add a node to the tree, according to the given key and value
//you have to use the exact algorithm described in the lecture notes
//so that you will have the exact same result as our demo and sample output
//it should do nothing to the tree and return false when there is already a node that has the same key
//otherwise, it should add the node and return true
//hint: you probably will have a statement to allocate the space for the new pair, like so: "new Pair<KeyType, ValueType>(key, value);"
bool add(KeyType key, ValueType value);
bool remove(KeyType key);
ValueType getValue(KeyType key);
int getHeight();
using Tree<Container, KeyType, ValueType>::data;
};
#include "BSTree.tpp"
#endif /* BSTREE_H_ */
I have a header file for a program that utilizes singly linked list. The data that is originally stored in the nodes were integers, however, in an attempt to use the template class, I tried to convert the Node class and AnyList class to template classes; however, when I compile, an error message that says "'Node": use of class template requires template argument list" appears. I've seen examples of template classes, but there's a bit of confusion since I'm trying to make two template classes in one header file.
#ifndef ANYLIST_H
#define ANYLIST_H
#include<iostream>
#include <string>
using namespace std;
template <typename T>
class Node
{
public:
Node() : data(0), next(NULL) {}
Node(T& theData, Node *newNext) : data(theData), next(newNext){}
Node* getNext() const { return next; }
T getData( ) const { return data; }
void setData(T& theData) { data = theData; }
void setNext(Node *newNext) { next = newNext; }
~Node(){}
private:
T data;
Node *next; //pointer that points to next node
};
template <typename T>
class AnyList
{
friend ostream& operator<<(ostream& out, const AnyList<T>& theList);
public:
AnyList();
void insert(const T& elem);
int getNumOfElem() const;
void destroyList();
~AnyList();
private:
Node *first;
int count;
};
#endif
Simply put, Node<> and List<> are different templates. So you need to forward the template parameter from List to Node.
Replace
Node *first;
By
Node<T> *first;
I'm trying my hand at templates, and thought I'd try to make a linked list using them. I've got a header file and a cpp file.
Header file:
#ifndef LINKED_LIST_H
#define LINKED_LIST_H
template <class T>
class Node {
public:
// Constructor and desconstructor
Node<T>(T value);
~Node();
// ---- Methods ----
void add(T value); // Add the value at the end of the list
void add(T value, int index); //
void remove(int index); //
void remove(T value); //
bool containts(T value); // Recursively check if our value it the supplied value
Node<T>* at(int index); // Return the Node at the given index
int size(); // Recursively get the size
void print(); // Print the value and move to the next one
Node* next; // Next Node in the list
T value; // Value of the Node
};
template <class T>
class LinkedList {
public:
// Constructor and deconstructor
LinkedList<T>();
~LinkedList<T>();
// ---- Methods ----
void add(T value); // Add a new Node at the end of the list with value
void add(T value, int index); // Add a new Node at the given index of the list with value
void remove(int index); // Remove the Node at the given index
void remove(T value); // Remove any Nodes with the given value
bool contains(T value); // If the List contains the supplied value
Node<T>* operator[](int index); // Node at the specified index
int size(); // Returns the number of Nodes in the list
bool empty(); // What do you think this does?
void print(); // Prints all the values in the List
private:
Node<T>* head; // The top of the List
Node<T>* latest; // Latest Node added
};
#endif
In my .cpp file, I try to define the Node's constructor using
#include "LinkedList.h"
template<class T> Node<T>::Node<T>(T value) {
}
However, on compilation I get this error:
./src/Util/LinkedList.cpp:3:19: error: 'Node::Node' names the constructor, not the type
template Node::Node(T value) {
^
./src/Util/LinkedList.cpp:3:19: error: and 'Node' has no template constructors
I shouldn't be defining the type should I? Since it's a template? Sorry if this is formatted badly, this is my first time using stack overflow.
The correct syntax you want is:
Node(T value); // not a template
And:
template<class T> Node<T>::Node(T value) {
The Node constructor itself is not a template, it takes a T - which is the class' template type. Now, if you wanted the constructor itself to be templated, that would look like:
template <typename U>
Node(U );
template <typename T>
template <typename U> // yep, twice
Node<T>::Node(U value)
{
..
}