I'm trying to implement an AVL tree and seem to be having issues with how I'm using my Node class. I'm getting the error C4430: missing type specifier with the second getHeight I thought I specified the type as Node for subtree?
template <typename T>
class SetAVL
{
public:
int getHeight()
{
return getHeight(root);
}
// Complaining about this line
int getHeight(const Node<T> *subtree)
{
// If we are at a leaf
if (subtree == NULL)
return 0;
return 1 + max(getHeight(subtree->left), getHeight(subtree->right));
}
void add(Node<T> *item)
{
Node<T> *t = new Node<T>(item);
insert(root, t);
}
void insert(Node<T> *root, Node<T> *t)
{
if (root == NULL)
root = t;
else
{
if (t->item < root->item)
insert(root->left, t);
else if (t->item != root->item)
insert(root->right, t);
else
delete t;
}
}
protected:
template <typename T>
class Node
{
public:
T item;
Node *left;
Node *right;
int height;
Node(T item)
{
this->item = item;
this->left = NULL;
this->right = NULL;
this->height = 0;
}
}
Node<T> *root;
int treeSize;
}
Seems need specify the correct type for left and right point
Node *left;
Node *right;
should be
Node<T> *left;
Node<T> *right;
I moved Node definition before using it. BTW, you lost a ';' at the end of class Node definition.
template <typename T>
class SetAVL
{
protected:
template <typename T>
class Node
{
public:
T item;
Node<T> *left;
Node<T> *right;
int height;
Node(T item)
{
this->item = item;
this->left = NULL;
this->right = NULL;
this->height = 0;
}
};
Node<T> *root;
int treeSize;
public:
int getHeight()
{
return getHeight(root);
}
int getHeight(const Node<T> *subtree)
{
// If we are at a leaf
if (subtree == NULL)
return 0;
return 1 + max(getHeight(subtree->left), getHeight(subtree->right));
}
void add(Node<T> *item)
{
Node<T> *t = new Node<T>(item);
insert(root, t);
}
void insert(Node<T> *root, Node<T> *t)
{
if (root == NULL)
root = t;
else
{
if (t->item < root->item)
insert(root->left, t);
else if (t->item != root->item)
insert(root->right, t);
else
delete t;
}
}
};
Hope it helps!
Related
I'm trying to create a binary search tree by keeping the path: each node has a link to its parent. Below is the classic binary search. How do I change it to be able to solve my problem?
I tried adding the "father" pointer to the struct but I have no problems understanding how and when to save it. I am new to this language so be patient. thank you so much
#include <iostream>
template <class T>
class BinaryTree
{
struct node {
T value;
struct node* right;
struct node* left;
};
public:
BinaryTree();
~BinaryTree();
void add(T val);
void printPreOrder();
void printInOrder();
void printPostOrder();
int size();
bool lookup(T val);
private:
struct node* root;
int treeSize;
void add(struct node** node, T val);
bool lookup(struct node* node, T val);
void printPreOrder(struct node* node);
void printInOrder(struct node* node);
void printPostOrder(struct node* node);
void deleteTree(struct node* node);
};
template <class T>
BinaryTree<T>::BinaryTree() {
this->root = NULL;
this->treeSize = 0;
}
template <class T>
BinaryTree<T>::~BinaryTree() {
deleteTree(this->root);
}
template <class T>
int BinaryTree<T>::size() {
return this->treeSize;
}
template <class T>
void BinaryTree<T>::add(T val) {
add(&(this->root), val);
}
template <class T>
void BinaryTree<T>::add(struct node** node, T val) {
if (*node == NULL) {
struct node* tmp = new struct node;
tmp->value = val;
tmp->left = NULL;
tmp->right = NULL;
*node = tmp;
this->treeSize++;
}
else {
if (val > (*node)->value) {
add(&(*node)->right, val);
}
else {
add(&(*node)->left, val);
}
}
}
template <class T>
void BinaryTree<T>::printInOrder() {
printInOrder(this->root);
std::cout << std::endl;
}
template <class T>
void BinaryTree<T>::printInOrder(struct node* node) {
if (node != NULL) {
printInOrder(node->left);
std::cout << node->value << ", ";
printInOrder(node->right);
}
}
template <class T>
void BinaryTree<T>::printPreOrder() {
printPreOrder(this->root);
std::cout << std::endl;
}
template <class T>
void BinaryTree<T>::printPreOrder(struct node* node) {
if (node != NULL) {
std::cout << node->value << ", ";
printInOrder(node->left);
printInOrder(node->right);
}
}
template <class T>
void BinaryTree<T>::printPostOrder() {
printPostOrder(this->root);
std::cout << std::endl;
}
template <class T>
void BinaryTree<T>::printPostOrder(struct node* node) {
if (node != NULL) {
printInOrder(node->left);
printInOrder(node->right);
std::cout << node->value << ", ";
}
}
template <class T>
void BinaryTree<T>::deleteTree(struct node* node) {
if (node != NULL) {
deleteTree(node->left);
deleteTree(node->right);
delete node;
}
}
template <class T>
bool BinaryTree<T>::lookup(T val) {
return lookup(this->root, val);
}
template <class T>
bool BinaryTree<T>::lookup(struct node* node, T val) {
if (node == NULL) {
return false;
}
else {
if (val == node->value) {
return true;
}
if (val > node->value) {
return lookup(node->right, val);
}
else {
return lookup(node->left, val);
}
}
}
I will give you the recursive solution since it is the natural way to implement it:
First it would be a good idea to define a constructor in your struct like so:
node(T value, node* left = nullptr, node* right = nullptr){
this->value = value;
this->left = left;
this->right = right;
}
Take out the struct in the struct node* root.
void insert(T value){
Node* temp = root;
insert(value, root);
}
//helper function
void insert(T value, Node* root){
if(root->left == nullptr && root->right == nullptr){
if(root->value < value){
root->left = new Node(value);
}
else{
root->right = new Node(value);
}
return;
}
if(value < root->value)insert(value, root->left);
else{
insert(value, root->right);
}
}
Not sure where you got your code it does not look correct....
I don't understand the need for pointer to pointer to struct node in your code. Pointer to struct node would suffice. As far as your question goes, you can pass the parent of current node as a third parameter in the method add. Initially it will be null. Now incase you have to go down to the child of the current node, then the current node becomes it's parent. When you have to allocate memory for value val, set the it's parent there.
template <class T>
void BinaryTree<T>::add(struct node** node, T val, struct node* parent = nullptr) {
if (*node == NULL) {
struct node* tmp = new struct node;
tmp->value = val;
tmp->left = NULL;
tmp->right = NULL;
temp->parent = parent;
*node = tmp;
this->treeSize++;
}
else {
if (val > (*node)->value) {
add(&(*node)->right, val, *node);
}
else {
add(&(*node)->left, val, *node;
}
}
}
So, I started learning and reading about OOP not so long ago, I've been implementing all the data structures I know using classes and objects just for overall practice and to get comfortable with using OOP in c++.
I'm implementing the tree data structure and I've been wondering how to call a method recursively(I'm aware that I have to pass in an argument) so that when I create an object in main and call a specific method it's written like the following a.inorder(); and not a.inorder(root) since root is a private attribute.
Is this possible ?
My code:
#include<iostream>
using namespace std;
struct node
{
int data;
node* left;
node* right;
};
class tree
{
private:
node* root;
public:
tree();
tree(int val);
void insert(int val);
void preorder();
void postorder();
void inorder();
int count();
};
tree::tree() : root { NULL }
{
}
tree::tree(int val)
{
root = new node;
root->data = val;
root->left = root->right = NULL;
}
void tree::insert(int val)
{
if (!root)
{
root = new node;
root->data = val;
root->left = root->right = NULL;
}
else
{
node* t = root;
node* p = NULL;
while (t)
{
p = t;
if (val > root->data)
t = root->right;
else
t = root->left;
}
t = new node;
t->data = val;
t->left = t->right = NULL;
if (p->data > t->data)
p->left = t;
else
p->right = t;
}
}
void tree::preorder()
{
if (root)
{
}
}
In your design, a node refers to itself. Since it is the node object that is recursive, you could define the recursive method on node:
struct node
{
int data;
node* left;
node* right;
void preorder() {
//...
left->preorder();
right->preorder();
}
};
And then, tree::preorder() would just dispatch a call to root->preorder().
Write a private static recursive function passing to it the pointer to the root node and call the function from the corresponding public non-static member function.
For example
public:
std::ostream & preorder( std::ostream &os = std::cout ) const
{
return preorder( root, os );
}
//...
private:
static std::ostream & preorder( const node *root, std::ostream &os );
//...
This is a comment rather than an actual answer, as it addresses a different issue than you are asking about. However, it is too long for a comment space, that's why I post it here.
I suppose you erroneously refer to root in this part
while (t)
{
p = t;
if (val > root->data)
t = root->right;
else
t = root->left;
}
IMHO it should look like this:
while (t)
{
p = t;
if (val > t->data)
t = t->right;
else
t = t->left;
}
Also compare the code to seek a place for insert with a code that makes an actual insertion:
if (p->data > t->data)
p->left = t;
else
p->right = t;
You've put a comparison subexpressions in reversed order - when seeking, you test whether the new value is greater than that in an existing node, but when inserting, you test whether the existing value is greater than the new one. If they differ, the code will work OK, because you also swapped left and right in the 'then' and 'else' branch.
However, if the values appear equal, the execution control will go to 'else' in both places. As a result the testing code may stop at empty left pointer, but then a new node would get appended to the right, which was not tested for being NULL.
Why would the tree class do intrinsic operations on node? The node class knows best the node's internal structure, so let it initialize itself. This will also help you to stick to the DRY principle and, indirectly, to the KISS principle, as well as the Single-responsibility principle.
struct node
{
int data;
node* left;
node* right;
node(int val) : data(val), left(NULL), right(NULL) {}
};
class tree
{
private:
node* root;
public:
tree();
tree(int val);
void insert(int val);
};
tree::tree() : root { NULL }
{
}
tree::tree(int val) : root(new node(val))
{
}
void tree::insert(int val)
{
if (!root)
{
root = new node(val);
}
else
{
node* t = root;
node* p = NULL;
while (t)
{
p = t;
if (val < t->data)
t = t->left;
else
t = t->right;
}
t = new node(val);
if (t->data < p->data)
p->left = t;
else
p->right = t;
}
}
Additionally, you can make insert recursive, too.
struct node
{
int data;
node* left;
node* right;
node(int val) : data(val), left(NULL), right(NULL) {}
};
class tree
{
private:
node* root;
public:
tree();
tree(int val);
void insert(int val);
protected:
void insertat(node* p, int val);
};
void tree::insert(int val)
{
if (!root)
root = new node(val);
else
insertat(root, val);
}
void tree::insertat(node* t, int val);
{
if (val < t->data)
{
if (t->left)
insertat(t->left, val);
else
t->left = new node(val);
}
else
{
if (t->right)
insertat(t->right, val);
else
t->right = new node(val);
}
}
#include<iostream>
#include<cstdio>
#include<sstream>
#include<algorithm>
#define pow2(n) (1 << (n))
using namespace std;
template<class T> struct avl_node
{
T data;
struct avl_node *left;
struct avl_node *right;
};
avl_node<int>* root;
template<class T>
class avlTree
{
public:
int height(avl_node<T> *);
int diff(avl_node<T> *);
avl_node<T> *rr_rotation(avl_node<T> *);
avl_node<T> *ll_rotation(avl_node<T> *);
avl_node<T> *lr_rotation(avl_node<T> *);
avl_node<T> *rl_rotation(avl_node<T> *);
avl_node<T> *balance(avl_node<T> *);
avl_node<T> *insert(avl_node<T> *, int );
void display(avl_node<T> *, int);
avlTree()
{
root = NULL;
}
};
int main()
{
int choice, item;
avlTree<int> avl;
while (1)
{
cout<<"\n---------------------"<<endl;
cout<<"AVL Tree "<<endl;
cout<<"\n---------------------"<<endl;
cout<<"1.Insert Element into the tree"<<endl;
cout<<"2.Display Balanced AVL Tree"<<endl;
cout<<"3.Exit"<<endl;
cout<<"Enter your Choice: ";
cin>>choice;
switch(choice)
{
case 1:
cout<<"Enter value to be inserted: ";
cin>>item;
root = avl.insert(root, item);
break;
case 2:
if (root == NULL)
{
cout<<"Tree is Empty"<<endl;
continue;
}
cout<<"Balanced AVL Tree:"<<endl;
avl.display(root, 1);
break;
case 3:
exit(1);
break;
default:
cout<<"Wrong Choice"<<endl;
}
}
return 0;
}
template<class T>
int avlTree<T>::height(avl_node<T> *temp)
{
int h = 0;
if (temp != NULL)
{
int l_height = height (temp->left);
int r_height = height (temp->right);
int max_height = max (l_height, r_height);
h = max_height + 1;
}
return h;
}
template<class T>
int avlTree<T>::diff(avl_node<T> *temp)
{
int l_height = height (temp->left);
int r_height = height (temp->right);
int b_factor= l_height - r_height;
return b_factor;
}
template<class T>
avl_node<T> *avlTree<T>::rr_rotation(avl_node<T> *parent)
{
avl_node *temp;
temp = parent->right;
parent->right = temp->left;
temp->left = parent;
return temp;
}
template<class T>
avl_node<T> *avlTree<T>::ll_rotation(avl_node<T> *parent)
{
avl_node *temp;
temp = parent->left;
parent->left = temp->right;
temp->right = parent;
return temp;
}
template<class T>
avl_node<T> *avlTree<T>::lr_rotation(avl_node<T> *parent)
{
avl_node *temp;
temp = parent->left;
parent->left = rr_rotation (temp);
return ll_rotation (parent);
}
template<class T>
avl_node<T> *avlTree<T>::rl_rotation(avl_node<T> *parent)
{
avl_node *temp;
temp = parent->right;
parent->right = ll_rotation (temp);
return rr_rotation (parent);
}
template<class T>
avl_node<T> *avlTree<T>::balance(avl_node<T> *temp)
{
int bal_factor = diff (temp);
if (bal_factor > 1)
{
if (diff (temp->left) > 0)
temp = ll_rotation (temp);
else
temp = lr_rotation (temp);
}
else if (bal_factor < -1)
{
if (diff (temp->right) > 0)
temp = rl_rotation (temp);
else
temp = rr_rotation (temp);
}
return temp;
}
template<class T>
avl_node<T> *avlTree<T>::insert(avl_node<T> *root, int value)
{
if (root == NULL)
{
root = new avl_node;
root->data = value;
root->left = NULL;
root->right = NULL;
return root;
}
else if (value < root->data)
{
root->left = insert(root->left, value);
root = balance (root);
}
else if (value >= root->data)
{
root->right = insert(root->right, value);
root = balance (root);
}
return root;
}
template<class T>
void avlTree<T>::display(avl_node<T> *ptr, int level)
{
int i;
if (ptr!=NULL)
{
display(ptr->right, level + 1);
printf("\n");
if (ptr == root)
cout<<"Root -> ";
for (i = 0; i < level && ptr != root; i++)
cout<<" ";
cout<<ptr->data;
display(ptr->left, level + 1);
}
}
Can you help me please? I must finish this task today.
1 error C2955: avl_node: use of template requires template argument list
2 error C2512: avl_node: unable to match function definition to an existing declaration
Along with Cyber's answer, you also need to make changes to temp variable.
template<class T>
avl_node<T> *avlTree<T>::rr_rotation(avl_node<T> *parent)
{
avl_node<T> *temp;
//rest of code
}
template<class T>
avl_node<T> *avlTree<T>::ll_rotation(avl_node<T> *parent)
{
avl_node<T> *temp;
// rest of code
}
template<class T>
avl_node<T> *avlTree<T>::lr_rotation(avl_node<T> *parent)
{
avl_node<T> *temp;
//rest of code
}
template<class T>
avl_node<T> *avlTree<T>::rl_rotation(avl_node<T> *parent)
{
avl_node<T> *temp;
//rest of code
}
template<class T>
avl_node<T> *avlTree<T>::insert(avl_node<T> *root, int value)
{
if (root == NULL)
{
root = new avl_node; //make it avl_node<T>
//rest of code
}
You need to add the template argument to the members within your structs, for example
template<class T>
struct avl_node
{
T data;
struct avl_node *left;
struct avl_node *right;
};
Should be
template<class T>
struct avl_node
{
T data;
struct avl_node<T> *left;
struct avl_node<T> *right;
};
This is true of the functions you define later which create or declare avl_node* variables, these should be using avl_node<T>* variables.
I am trying to implement BST with unique_ptr. I want to return the node with the minimum value in BST. I know how to return the minimum value and I wrote the function for it but what if I want to return node? Is it possible with the classes I have?
#include <iostream>
#include <memory>
template<class T>
class BinarySearchTree{
struct TreeNode;
typedef std::unique_ptr<TreeNode> spTreeNode;
struct TreeNode{
T data;
spTreeNode left;
spTreeNode right;
TreeNode(const T & value):data(value),left(nullptr),right(nullptr){}
};
spTreeNode root;
bool insert(spTreeNode &node);
void print(const spTreeNode&) const ;
public:
BinarySearchTree();
void insert( const T & node);
void print()const;
T getMin();
};
template<class T>
BinarySearchTree<T>::BinarySearchTree():root(nullptr){}
template<class T>
void BinarySearchTree<T>::insert(const T & ref)
{
std::unique_ptr<TreeNode> node(new TreeNode(ref));
if (root == nullptr) {
root = std::move(node);
} else {
TreeNode* temp = root.get();
TreeNode* prev = root.get();
while (temp != nullptr) {
prev = temp;
if (temp->data < ref)
temp = temp->right.get();
else
temp = temp->left.get();
}
if (prev->data < ref)
prev->right = std::move(node);
else
prev->left = std::move(node);
}
}
template<class T>
T BinarySearchTree<T>::getMin()
{
TreeNode* temp = root.get();
TreeNode *prev = nullptr;
while (temp)
{
prev = temp;
temp = temp->left.get();
}
return prev->data;
}
int main()
{
BinarySearchTree<int> bst;
bst.insert(13);
bst.insert(3);
bst.insert(5);
bst.insert(31);
bst.insert(511);
bst.insert(311);
std::cout << bst.getMin(); // Works but what if I want to return the Node?
return 0;
}
You would have to decide the interface you want. Do you want to return a const pointer to the extant TreeNode? A const reference to the TreeNode? A copy of the TreeNode? The key is to think about how long references/pointers will be valid.
I frankly don't think any of those are good ideas for a public interface. So let's say you made getMinNode() private, and kept getMin() public:
// Returns non-owning pointer; do not attempt to delete TreeNode.
template<class T>
const BinarySearchTree<T>::TreeNode* BinarySearchTree<T>::getMinNode() const
{
// Like getMin(), but return prev
// Does this work for empty BinarySearchTree?
TreeNode* temp = root.get();
TreeNode *prev = nullptr;
while (temp)
{
prev = temp;
temp = temp->left.get();
}
return prev;
}
template<class T>
T BinarySearchTree<T>::getMin() const // member function is const
{
return getMinNode()->data;
}
I have written an implementation of BST-Tree but the key can be only string type. I would like to use that tree with other types of keys. I know that I would have to define a template, but do not know how to do it so the key will have T type. The examples show all but not important stuff.
using namespace std;
int ASCENDING = 0, DESCENDING = 1;
class Node {
public:
string key; //I would like to change type to T
Node* left;
Node* right;
Node(string key) {
this->key = key;
left = NULL;
right = NULL;
}
};
class BST {
public:
Node* root;
BST(string key) {
root = new Node(key);
}
void insert(string value){
if(root == NULL)
root = new Node(value);
else
insertHelper(root, value);
}
void insertHelper(Node* node, string value){
if(value < node->key){
if(node->left == NULL)
node->left = new Node(value);
else
insertHelper(node->left, value);
}
else{
if(node->right == NULL)
node->right = new Node(value);
else
insertHelper(node->right, value);
}
}
void print(int order){
show(order, root);
}
~BST(){
//delete all nodes
}
private:
void show(int order, Node* n){
Node* pom = n;
if(order == ASCENDING){
if(pom != NULL){
show(order, n->left);
cout<<n->key<<endl;
show(order, n->right);
}
}else{
if(pom != NULL){
show(order, n->right);
cout<<n->key<<endl;
show(order, n->left);
}
}
}
};
This should cover the basic setup and the rest of the changes should be similar:
template <typename T>
class Node {
public:
T key; //I would like to change type to T
^^^^^ Type now T
Node<T>* left;
Node<T>* right;
Node(T key) {
this->key = key;
left = NULL;
right = NULL;
}
};
template <typename T>
class BST {
public:
Node<T>* root;
^^^^^^^ Node now will become Node<T> in the rest of the code as well
BST(T key) {
root = new Node<T>(key);
}
// rest of code
};