BSTree add function - c++

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_ */

Related

BST with function ptr, How to add in extra argument?

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.

std::variant 'attempting to reference a deleted function'

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'm trying to make a function "InOrder", which does inorder traversing in Binary Search

I'm trying to make InOrder in void-type, which executes in-order traversal in a binary search tree.
//Code Provided by Professor
//Program 5.1:Inorder traversal of a binary tree
//===============================================
template <class T>
void Tree<T>::Inorder()
{// Driver.
Inorder(root);
}
template <class T>
void Tree<T>::Inorder(TreeNode<T> *currentNode)
{// Workhorse.
if (currentNode) {
Inorder(currentNode->leftChild);
Visit(currentNode);
Inorder(currentNode->rightChild);
}
}
The above code is provided by Professor, as a reference making my own InOrder function.
This Code is how I declared the elements(requisites) for my binary search tree.
#include <iostream>
using namespace std;
template<class K, class E>
class BinarySearchTree
{
public:
virtual void Insert(const pair<K, E>&) = 0;
virtual void Delete(const K&) = 0;
virtual pair<K, E>*Get(const K&) const = 0;
virtual void InOrder()const;
};
template<class T>
struct TreeNode {
T data;
TreeNode<T> *leftChild;
TreeNode<T> *rightChild;
TreeNode(T node) : data(node), leftChild(0), rightChild(0) {}
};
template<class K, class E>
class BST : BinarySearchTree<K, E> {
public:
BST() : root(0) {}
void Insert(const pair<K, E>&);
void Delete(const K&);
pair<K, E>*Get(const K&)const;
void InOrder()const;
private:
TreeNode<pair<K, E>> *root;
};
Other functions work well, and I would appreciate any help with making InOrder function, using C++.
The concept of in order is just the concept of order. You must also say what should be done in that order. The code provided by your professor calls a visit function.
That means that in your implementation, you also need such a visit function. It can either be hardcoded (display a node on cout) or better passed as a parameter. In that case, you should declare InOrder as:
void InOrder(void (*visit)(const pair<K, E>&))const;
And later call it (for example with a lambda function) as:
BST<int, string> bst;
...
bst.InOrder([](const pair<int, string>&ke) {
cout << "K: " << ke.first << " -E: " << ke.second << "\n";
});
A possible implementation mimicing your professor's code could be:
template<class K, class E>
void BST<K,E>::doInOrder(const TN* root, void (*visit)(const pair<K, E>&)) {
if (root) {
doInOrder(root->leftChild, visit);
visit(root->data);
doInOrder(root->rightChild, visit);
}
}
template<class K, class E>
void BST<K,E>::InOrder(void (*visit)(const pair<K, E>&))const {
doInOrder(root, visit);
}

Extends Balanced BST into C++ STL Map

I've implemented a balanced binary search tree (Red-black tree) for practice purposes. here is the header of data-structure of underlying nodes and methods I've implemented so far:
#ifndef BST_H
#define BST_H
template <typename T>
class treeNode {
public:
treeNode *left;
treeNode *right;
T key;
treeNode(T key)
: key(key)
, left(nullptr)
, right(nullptr) {
}
};
template <typename T>
class BST {
public:
BST() {
root = nullptr;
nodes = 0;
}
BST(BST const& rhs);
BST& operator = (BST rhs) {
this->swap(rhs);
}
BST& operator = (BST&& rhs) {
this->swap(rhs);
}
~BST() {
clear(root);
}
void swap(BST& other) {
std::swap(root, other.root);
std::swap(nodes, other.nodes);
}
void clear(treeNode<T>* node) {
if(node) {
if(node->left) clear(node->left);
if(node->right) clear(node->right);
delete node;
}
}
bool isEmpty() const {
return root == nullptr;
}
void inorder(treeNode<T>*);
void traverseInorder();
void preorder(treeNode<T>*);
void traversePreorder();
void postorder(treeNode<T>*);
void traversePostorder();
void insert(T const& );
void remove(T const& );
treeNode<T>* search(const T &);
treeNode<T>* minHelper(treeNode<T>*);
treeNode<T>* min();
treeNode<T>* maxHelper(treeNode<T>*);
treeNode<T>* max();
size_t size() const;
void sort();
treeNode<T>* inOrderSuccessor(treeNode<T>*);
bool isBST(treeNode<T>*) const;
bool isBST() const;
private:
treeNode<T> *root;
size_t nodes;
};
#endif
I intend to implement C++ STL map (I've already implemented STL unordered_map using Hashtable) for which the underlying data-structure is Red-Black Tree AFAIK. How I can extend my tree to a key-value generic type map?
No need of any sort of source code. Some intuition will suffice. Thanks :)
With intuition: T will probably be pair<const key_type,mapped_type>. I'm Assuming that currently you use node.key < another_node.key for comparisons. That will not do, because a map should be only using the first part of the pair for that. You could add a Compare functor as a template parameter (in similar manner as you'll have to for your map class) to your tree to make it useful for implementing a stl compatible map.
You may choose to design your tree so that key and value classes are separate rather than combined. Here's example code for the template definition:
template<class Key, class Value, class Comp=std::less<Key>>
class BST {
Compare comp;
public:
BST(const Comp& comp = Comp()): comp(comp)
//...
// usage
if(comp(node.key, another_node.key)) {
// node is considered to be strictly before another_node
You can use std::less as a sensible default parameter for other users of the tree, but the map implementation should forward the comparator which was given for the map.
A fully stl compatible container should support custom allocators too and to make that possible, so must the internal tree structure.

Working with templates and error in C++

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)
{
//...
}
//...
};