C++ template of BinarySearchTreeNode - c++

Hey I have this template of BinarySearchTreeNode in which i have to implement the following methods
Constructors
Destructor
Empty
leaf
Height
insert
i am done with the constructors and the insert part but i am facing issues with the destructor and the height functions please help me implement these methods
Special care is required for the implementation of method height(). The empty tree has no
height, hence height() must throw a domain_error exception in this case. For interior
nodes, however, if a subtree of a given BinaryTreeNode is empty, then this subtree
contributes a height of zero to the interior node. In other words, the smallest height of any
non-empty BinaryTreeNode is zero. Remember, interior nodes add one to the maximum
height of their subtrees.
Help me with these methods i am super new to DSA and c++ any help is greatly appreciated
#pragma once
#include <stdexcept>
#include <algorithm>
template <typename T>
struct BinaryTreeNode
{
using BNode = BinaryTreeNode<T>;
using BTreeNode = BNode *;
T key;
BTreeNode left;
BTreeNode right;
static BinaryTreeNode<T> NIL;
const T &findMax() const
{
if (empty())
{
throw std::domain_error("Empty tree encountered.");
}
return right->empty() ? key : right->findMax();
}
const T &findMin() const
{
if (empty())
{
throw std::domain_error("Empty tree encountered.");
}
return left->empty() ? key : left->findMin();
}
bool remove(const T &aKey, BTreeNode aParent)
{
BTreeNode x = this;
BTreeNode y = aParent;
while (!x->empty())
{
if (aKey == x->key)
{
break;
}
y = x; // new parent
x = aKey < x->key ? x->left : x->right;
}
if (x->empty())
{
return false; // delete failed
}
if (!x->left->empty())
{
const T &lKey = x->left->findMax(); // find max to left
x->key = lKey;
x->left->remove(lKey, x);
}
else
{
if (!x->right->empty())
{
const T &lKey = x->right->findMin(); // find min to right
x->key = lKey;
x->right->remove(lKey, x);
}
else
{
if (y != &NIL) // y can be NIL
{
if (y->left == x)
{
y->left = &NIL;
}
else
{
y->right = &NIL;
}
}
delete x; // free deleted node
}
}
return true;
}
// Implement theses
BinaryTreeNode() : key(T()), left(&NIL), right(&NIL)
{
}
BinaryTreeNode(const T &aKey) : key(aKey), left(&NIL), right(&NIL)
{
}
BinaryTreeNode(T &&aKey) : key(std::move(aKey)), left(&NIL), right(&NIL)
{
}
~BinaryTreeNode()
{
}
bool empty() const
{
return this == &NIL;
}
bool leaf() const
{
return left == &NIL && right == &NIL;
}
size_t height() const
{
}
bool insert(const T &aKey)
{
if (aKey == key || empty())
return false;
if (aKey < key)
{
if (!left->empty())
return left->insert(aKey);
left = new BinaryTreeNode(aKey);
}
else
{
if (!right->empty())
return right->insert(aKey);
right = new BinaryTreeNode(aKey);
}
return true;
}
};
template <typename T>
BinaryTreeNode<T> BinaryTreeNode<T>::NIL;

Related

extract Min function is not working properly

I got an assignment but I'm stuck in the titled problem. It will be very glad that you will help me to solve this. The quick over review I have provided the classes and main file for which I have to implemented the function and run the code. There are two files named fheap.hpp and djstra.hpp and the main file.
int main(){
// Fibonacci Heap
FibonacciHeap<int> heap(3);
std::cout<<(heap.get_min()==std::nullopt)<<std::endl;
std::vector<int> inserted;
for(int i = 0 ; i < 15 ; ++i) {
int temp = rand() % 100+1;
heap.insert(temp);
cout << temp;
cout << "inserted & min :";
cout << heap.get_min().value() << endl;
}
std::cout<<heap.get_min().value()<<std::endl;
for (int j = 0; j < 15; ++j) {
int min_value = heap.extract_min().value();
cout << "min_value: ";
std::cout << min_value;
cout << " size: ";
cout << heap.size()<<endl;
}
// Dijkstra's Algorithm
edges_t edges1 = {{0, 1, 3.0f},
{0, 2, 1.0f},
{1, 2, 7.0f},
{1, 3, 5.0f},
{1, 4, 1.0f},
{2, 3, 2.0f},
{3, 4, 7.0f}};
Graph g1(5, edges1, GraphType::UNDIRECTED);
std::unordered_map<vertex_t, std::optional<std::tuple<vertex_t, edge_weight_t>>> result
= dijkstra_shortest_path(g1, 2);
// Previous vertex of src are not checked.
std::vector<vertex_t> previous = {2, 0, (vertex_t)-1, 2, 1};
std::vector<edge_weight_t> dist = {1.0f, 4.0f, 0.0f, 2.0f, 5.0f};
// The printed result should be same as above.
for(size_t i = 0 ; i < 5 && i!=2 ; ++i) {
std::cout<<"[vertex i] ";
std::cout<<"previous: "<<std::get<0>(result[i].value())<<", ";
std::cout<<"distance: "<<std::get<1>(result[i].value())<<std::endl;
}
return 0;
}
Suprisingly the djstra part is giving me the required output. second file loop in the main section throws memory error Edit: ( meaning it exits the program with some memory address and sometimes show what() std:: optional error). The fheap class is below that are responsible for it are below:
#ifndef __FHEAP_H_
#define __FHEAP_H_
#include <iostream>
#include <initializer_list>
#include <optional>
#include <vector>
#include <cmath>
#include <memory>
#include <queue>
#include <list>
template <typename T>
class PriorityQueue {
public:
virtual void insert(const T& item) = 0;
virtual std::optional<T> extract_min() = 0;
virtual bool is_empty() const = 0;
};
template <typename T>
class FibonacciNode {
public:
// Constructors
FibonacciNode()
:key(), degree(0), marked(false), child(nullptr), right(nullptr) {}
FibonacciNode(const T& item)
:key(item), degree(0), marked(false), child(nullptr), right(nullptr) {}
// Destructor
~FibonacciNode() = default;
T key;
size_t degree;
bool marked;
std::shared_ptr<FibonacciNode<T>> right;
std::shared_ptr<FibonacciNode<T>> child;
// NOTE: To prevent circular reference, left/parent pointer should be set to weak_ptr.
std::shared_ptr<FibonacciNode<T>> left;
std::shared_ptr<FibonacciNode<T>> parent;
};
template <typename T>
class FibonacciHeap : public PriorityQueue<T> {
public:
// Constructors
FibonacciHeap()
: min_node(nullptr), size_(0) {}
FibonacciHeap(const T& item)
: min_node(nullptr), size_(0) { insert(item); }
// Disable copy constructor.
FibonacciHeap(const FibonacciHeap<T> &);
// Destructor
//~FibonacciHeap();
void insert(const T& item) override;
void insert(std::shared_ptr<FibonacciNode<T>>& node);
// Return raw pointer of the min_node.
FibonacciNode<T>* get_min_node() { return min_node.get(); }
std::optional<T> get_min() const;
std::optional<T> extract_min() override;
std::optional<T> extract_min1();
void decrease_key(std::shared_ptr<FibonacciNode<T>>& x, T new_key);
void remove(std::shared_ptr<FibonacciNode<T>>& node);
bool is_empty() const override { return !size_; }
size_t size() const { return size_; }
private:
std::shared_ptr<FibonacciNode<T>> min_node;
std::shared_ptr<FibonacciNode<T>> min;
size_t size_;
void consolidate();
void merge(std::shared_ptr<FibonacciNode<T>>& x, std::shared_ptr<FibonacciNode<T>>& y);
void cut(std::shared_ptr<FibonacciNode<T>>& x);
void recursive_cut(std::shared_ptr<FibonacciNode<T>>& x);
};
template <typename T>
void FibonacciHeap<T>::insert(const T& item) {
std::shared_ptr<FibonacciNode<T>> node = std::make_shared<FibonacciNode<T>>(item);
insert(node);
}
template <typename T>
std::optional<T> FibonacciHeap<T>::get_min() const {
if (min_node) {
return min_node->key;
} else {
return std::nullopt;
}
}
template <typename T>
void FibonacciHeap<T>::insert(std::shared_ptr<FibonacciNode<T>>& node) {
// Make the new node the right sibling of the min_node, if it exists
if (min_node) {
node->right = min_node->right;
min_node->right = node;
node->left = min_node;
node->right->left = node;
}
// Otherwise, make the new node the min_node and its own right sibling
else {
min_node = node;
node->right = node;
node->left = node;
}
// If the new node has a smaller key than the current min_node, update min_node
if (node->key < min_node->key) {
min_node = node;
}
// Increase the size of the heap
++size_;
}
template <typename T>
std::optional<T> FibonacciHeap<T>::extract_min() {
// Return nullopt if the heap is empty
if (!min_node) {
return std::nullopt;
}
// Store the min_node in a temporary variable
std::shared_ptr<FibonacciNode<T>> z = min_node;
// If the min_node has children, add them to the root list
if (z->child) {
std::shared_ptr<FibonacciNode<T>> child = z->child;
do {
child->parent.reset();
child = child->right;
} while (child != z->child);
merge(min_node, z->child);
}
// Remove the min_node from the root list
std::shared_ptr<FibonacciNode<T>> left = z->left;
std::shared_ptr<FibonacciNode<T>> right = z->right;
left->right = right;
right->left = left;
// If the min_node was the only node in the heap, set min_node to nullptr
if (z == right) {
min_node.reset();
}
// Otherwise, set the new min_node to be the node that was previously to the right of z
else {
min_node = right;
consolidate();
}
// Decrease the size of the heap
--size_;
// Return the key of the extracted min_node
return z->key;
}
template <typename T>
void FibonacciHeap<T>::decrease_key(std::shared_ptr<FibonacciNode<T>>& x, T new_key) {
// If the new key is greater than the current key, throw an exception
if (new_key > x->key) {
throw std::invalid_argument("New key is greater than current key.");
}
// Update the key of the node
x->key = new_key;
// If the node has a parent and its new key is smaller than its parent's key, cut it from its parent and add it to the root list
auto parent = x->parent.lock();
if (parent && x->key < parent->key) {
cut(x);
}
// If the node's new key is smaller than the current min_node's key, update min_node
if (x->key < min_node->key) {
min_node = x;
}
}
template <typename T>
void FibonacciHeap<T>::remove(std::shared_ptr<FibonacciNode<T>>& x) {
// Set the key of the node to be removed to the minimum value
x->key = std::numeric_limits<T>::min();
// Perform a decrease key operation on the node to be removed
decrease_key(x, std::numeric_limits<T>::min());
// Extract the minimum value, which should be the node to be removed
extract_min();
}
template <typename T>
void FibonacciHeap<T>::consolidate() {
float phi = (1 + sqrt(5)) / 2.0;
int len = int(log(size_) / log(phi)) + 10;
std::vector<std::shared_ptr<FibonacciNode<T>>> A(len, nullptr);
std::shared_ptr<FibonacciNode<T>> w = min_node;
std::shared_ptr<FibonacciNode<T>> x = w;
do {
x = x->right;
std::shared_ptr<FibonacciNode<T>> y = x;
int d = y->degree;
while (A[d]) {
std::shared_ptr<FibonacciNode<T>> z = A[d];
if (y->key > z->key) {
std::swap(y, z);
}
merge(y, z);
A[d] = nullptr;
++d;
}
A[d] = y;
} while (w != x);
min_node.reset();
for (int i = 0; i < len; ++i) {
if (A[i]) {
if (min_node) {
A[i]->right = min_node->right;
min_node->right = A[i];
A[i]->left = min_node;
A[i]->right->left = A[i];
if (A[i]->key < min_node->key) {
min_node = A[i];
}
}
else {
min_node = A[i];
min_node->right = min_node;
min_node->left = min_node;
}
}
}
}
template <typename T>
void FibonacciHeap<T>::merge(std::shared_ptr<FibonacciNode<T>>& x, std::shared_ptr<FibonacciNode<T>>& y) {
// Make x the right sibling of y
x->right = y->right;
y->right->left = x;
y->right = x;
x->left = y;
// If x has a smaller key than y, make x the new min_node
if (x->key < y->key) {
min_node = x;
}
// Otherwise, make y the new min_node
else {
min_node = y;
}
// Increase the size of the heap
size_ += 2;
}
template <typename T>
void FibonacciHeap<T>::cut(std::shared_ptr<FibonacciNode<T>>& x) {
// Get a pointer to the parent of x
auto parent = x->parent;
// If x has no parent, we do not need to cut it
if (!parent) return;
// Remove x from the child list of parent
if (x->right == x) {
parent->child = nullptr;
}
else {
x->right->left = x->left;
x->left->right = x->right;
if (parent->child == x) {
parent->child = x->right;
}
}
// Decrease the degree of parent
--parent->degree;
// Add x to the root list of the heap
x->right = min_node->right;
min_node->right = x;
x->left = min_node;
x->right->left = x;
// Clear the parent and marked fields of x
x->parent.reset();
x->marked = false;
}
template <typename T>
void FibonacciHeap<T>::recursive_cut(std::shared_ptr<FibonacciNode<T>>& x) {
// Get the parent of the node
auto parent = x->parent.lock();
// If the node has a parent, cut it from the parent and perform a recursive cut on the parent
if (parent) {
if (x->marked) {
// Cut the node from the parent
cut(x);
// Perform a recursive cut on the parent
recursive_cut(parent);
}
// If the node is not marked, mark it
else {
x->marked = true;
}
}
}
#endif // __FHEAP_H_
I know, I'm asking a very long question. I've tried every approach but it's not solving.
I Tried debugging the code and introducing cout operations where I think is error after debugging is in the line
`
std::shared_ptr<FibonacciNode<T>> z = A[d];
I tried ArrayList but still no change.
Edit: Second for loop means the 2nd loop in int main ()

C++ shared_from_this() returns exception with template class

I have problem with shared_ptr and 'this' pointer. I found sollution to use enable_shared_from_this but:
std::shared_ptr<Binary_search_tree> x = shared_from_this();
throws exception. How to use it properly in my case?
here is code with context:
#pragma once
#include <memory>
#include <string>
bool def_comparator(int x, int y) {
if (x>y)
{
return true;
}
else {
return false;
}
};
template <typename T>
class Binary_search_tree : public std::enable_shared_from_this<Binary_search_tree<T>>
{
public:
std::shared_ptr<Binary_search_tree> up;
std::shared_ptr<Binary_search_tree> left;
std::shared_ptr<Binary_search_tree> right;
int key;
T data;
bool(*comparator)(int, int);
Binary_search_tree(T x, const int key, bool(*comparator)(int, int))
{
if (comparator==NULL)
{
this->comparator = &def_comparator;
}
else {
this->comparator = comparator;
}
this->data = x;
this->key = key;
}
Binary_search_tree()
{
}
~Binary_search_tree()
{
}
bool insert(T data, const int key)
{
std::shared_ptr<Binary_search_tree> y;
std::shared_ptr<Binary_search_tree> x = shared_from_this();
if (comparator(key, x->key))
{
x = x->left;
}
else {
x = x->right;
}
while (x != NULL)
{
y = x;
if (comparator(key,x->key))
{
x = x->left;
}
else {
x = x->right;
}
}
Binary_search_tree<T> *tmp = new Binary_search_tree<T>(data, key, this->comparator);
tmp->up = y;
if (tmp->key == y->key)
{
return false;
}
if (comparator(tmp->key,y->key))
{
y->left = shared_ptr<Binary_search_tree<T>>(tmp);
}
else {
y->right = shared_ptr<Binary_search_tree<T>>(tmp);
}
return true;
}
}
EDIT: I added whole insert method code
#Tyker I don't try to access members that way, I need to go throught my tree to add new element using x and ypointer. If there is no 'next element' the pointer stays as is and then new element is added.
#G.M. do you mean sth like this:
std::shared_ptr<Binary_search_tree<T>> x(new Binary_search_tree<T>);
x = shared_from_this();

Binary tree pointer to the root needs to be referenced and dereferenced. Why?

My question is why do I need to dereference and reference a pointer for the following code to work? Doesn't ref/deref cancel each other?
I would really appreciate if anyone could explain it like I'm five :)
Code:
template <typename T>
class binNode {
private:
T key;
public:
binNode * left;
binNode * right;
binNode * parent;
binNode() {
this->left = NULL;
this->right = NULL;
this->parent = NULL;
}
// arg constructor:
binNode (T key) {
this->key = key;
this->left = NULL;
this->right = NULL;
this->parent = NULL;
}
T getKey() {
return this->key;
}
void setKey(T key) {
this->key = key;
}
};
template<typename T> class Tree {
private:
binNode <T> *root;
public:
Tree() {
this->root = NULL;
}
Tree(binNode <T> * node) {
node->parent = NULL;
this->root = node;
}
/* THIS IS THE PART I DON'T GET */
void addNode(binNode<T> *&x, binNode<T> * node) { // what's up with the *&???
if (x == NULL) {
x = node;
return;
} else if (x->getKey() == node->getKey()) {
node->left = x;
node->parent = x->parent;
x->parent = node;
return;
}
if (node->getKey() < x->getKey()) {
addNode(x->left, node);
} else {
addNode(x->right, node);
}
}
void addNode(binNode<T> * node) {
addNode(this->root, node);
}
binNode<T> * treeSearch(binNode<T> * x, T key) {
if (x == NULL || key == x->getKey()) {
return x;
}
if (key < x->getKey()) {
return treeSearch(x->left, key);
} else {
return treeSearch(x->right, key);
}
}
void printOrdered() {
inorderTreeWalk(root);
cout << endl;
}
void inorderTreeWalk(binNode<T> * node) {
if (node != NULL) {
inorderTreeWalk(node->left);
cout << node->getKey() << '\t';
inorderTreeWalk(node->right);
}
}
};
Here is the main function (#inlude is not included)
int main() {
Tree<int> T (new binNode<int>(10));
// Tree<int> T = new binNode<int>(10);
T.addNode(new binNode<int> (11));
T.addNode(new binNode<int> (9));
T.addNode(new binNode<int> (8));
T.addNode(new binNode<int> (12));
T.printOrdered();
}
That's not a reference / dereference of a pointer, it's a reference to a pointer. It is necessary because...
void addNode(binNode<T> *&x, binNode<T> * node) {
if (x == NULL) {
x = node; // ...here...
return;
} else // ...
...you are assigning to the parameter x.
If you hadn't passed the pointer x by reference, you would assign to the local copy of the parameter:
void addNode(binNode<T> * x, binNode<T> * node) {
if (x == NULL) {
x = node; // this acts on the local copy only, and thus does nothing.
return;
} else // ...
Via the pointer (without the reference), you get a local copy of the address. Which means you can manipulate the value behind the pointer (in this case *x) which would change. But if you change the address itself, the address would behave like a local copy and you lose the address-changes after leaving the method.

Need help, AVL Tree of objects

Our teacher provided us with the AVL_Tree.h and AVL_Node.h
I am trying to declare a new AVL_Tree of Folder (class that I created). However I keep getting the same error
error C2784: 'bool std::operator <(const std::vector<_Ty,_Ax> &,const
std::vector<_Ty,_Ax> &)' : could not deduce template argument for 'const
std::vector<_Ty,_Ax> &' from 'const AVLNode<Item_Type>'
Here is the AVL_Tree class
#ifndef AVL_TREE_H
#define AVL_TREE_H
#include "AVL_Node.h"
template<typename Item_Type>
class AVL_Tree{
public:
AVL_Tree() : root(NULL){
}
AVL_Tree(const Item_Type& the_data, const AVL_Tree<Item_Type>& left_child = AVL_Tree(),
const AVL_Tree<Item_Type>& right_child = AVL_Tree()) :
root(new AVLNode<Item_Type>(the_data, left_child.root,
right_child.root)) {}
/** Return the left-subtree */
AVL_Tree<Item_Type> get_left_subtree() const {
if (root == NULL) {
throw std::invalid_argument("get_left_subtree on empty tree");
}
return AVL_Tree<Item_Type>(root->left);
}
/** Return the right-subtree */
AVL_Tree<Item_Type> get_right_subtree() const {
if (root == NULL) {
throw std::invalid_argument("get_right_subtree on null tree");
}
return AVL_Tree<Item_Type>(root->right);
}
/** Return the data field of the root
#throws std::invalid_argument if null tree
*/
const Item_Type& AVL_Tree<Item_Type>::get_data() const {
if (root == NULL) {
throw std::invalid_argument("get_data on null tree");
}
return root->data;
}
bool is_null() const {
return root == NULL;
}
/** Indicate that this tree is a leaf. */
bool is_leaf() const {
if (root != NULL) {
return root->left == NULL && root->right == NULL;
}
else
return true;
}
virtual bool insert(const Item_Type& item) {
return insert(this->root, item);
}
bool erase(const Item_Type& item) {
return erase(this->root, item);
}
const Item_Type* find(const Item_Type& item) const {
return find(this->root, item);
}
protected:
AVLNode<Item_Type>* root;
AVL_Tree(AVLNode<Item_Type>* new_root) : root(new_root) {}
const Item_Type* find(AVLNode<Item_Type>* local_root, const Item_Type& target) const {
if (local_root == NULL)
return NULL;
if (target < local_root->data)
return find(local_root->left, target);
else if (local_root->data < target)
return find(local_root->right, target);
else
return &(local_root->data);
}
bool erase(AVLNode<Item_Type>*& local_root, const Item_Type& item) {
if (local_root == NULL) {
return false;
}
else {
if (item < local_root->data){
bool return_value = erase(local_root->left, item);
if (return_value){
adjust_balance(local_root);
rebalance(local_root);
}
return return_value;
}
else if (local_root->data < item){
bool return_value = erase(local_root->right, item);
if (return_value){
adjust_balance(local_root);
rebalance(local_root);
}
return return_value;
}
else {
AVLNode<Item_Type>* old_root = local_root;
if (local_root->left == NULL)
local_root = local_root->right;
else if (local_root->right == NULL)
local_root = local_root->left;
else
replace_parent(old_root, old_root->left);
if (local_root != NULL){
adjust_balance(local_root);
rebalance(local_root);
}
delete old_root;
return true;
}
}
}
void rebalance(AVLNode<Item_Type>*& local_root){
if (local_root->balance() <= -2)
rebalance_left(local_root);
else if (local_root->balance() >= 2)
rebalance_right(local_root);
}
void adjust_balance(AVLNode<Item_Type>*& node){
node->update_left_height();
node->update_right_height();
}
void replace_parent(AVLNode<Item_Type>*& old_root, AVLNode<Item_Type>*& local_root) {
if (local_root->right != NULL) {
replace_parent(old_root, local_root->right);
adjust_balance(local_root);
rebalance(local_root);
}
else {
old_root->data = local_root->data;
old_root = local_root;
if (local_root->left != NULL){
local_root = local_root->left;
adjust_balance(local_root);
}
else
local_root = NULL;
}
}
bool insert(AVLNode<Item_Type>*& local_root, const Item_Type& item) {
if (local_root == NULL) {
local_root = new AVLNode<Item_Type>(item);
return true;
}
else {
if (item < local_root->data) {
bool return_value = insert(local_root->left, item);
if (return_value){ //we have inserted the item
local_root->update_left_height(); //left height might increase by 1
if (local_root->balance() <= -2) // local root is now critically unbalanced
rebalance_left(local_root);
}
return return_value;
}
else if (local_root->data < item) {
bool return_value = insert(local_root->right, item);
if (return_value){
local_root->update_right_height(); //right height might increase by 1
if (local_root->balance() >= 2) // local root is now critically unbalanced
rebalance_right(local_root);
}
return return_value;
}
else
return false; //item already exists
}
}
void rebalance_left(AVLNode<Item_Type>*& local_root) {
if (local_root->left->balance() > 0) // See whether left-right-heavy
rotate_left(local_root->left); // Perform left rotation
// Finally rotate right
rotate_right(local_root);
}
void rebalance_right(AVLNode<Item_Type>*& local_root) {
if (local_root->right->balance() < 0) // See whether right-left-heavy
rotate_right(local_root->right); // Perform left rotation
// Finally rotate right
rotate_left(local_root);
}
void rotate_right(AVLNode<Item_Type>*& local_root) {
AVLNode<Item_Type>* temp = local_root->left;
local_root->left = temp->right;
//adjust the balances
local_root->update_left_height();
temp->right = local_root;
temp->update_right_height();
local_root = temp;
}
void rotate_left(AVLNode<Item_Type>*& local_root) {
AVLNode<Item_Type>* temp = local_root->right;
local_root->right = temp->left;
//adjust the balances
local_root->update_right_height();
temp->left = local_root;
temp->update_left_height();
local_root = temp;
}
};
#endif
This is the AVL_Node class
#ifndef AVLNODE_H_
#define AVLNODE_H_
#include <sstream>
template<typename Item_Type>
struct AVLNode {
// Additional data field
int right_height;
int left_height;
AVLNode<Item_Type>* left;
AVLNode<Item_Type>* right;
Item_Type data;
// Constructor
AVLNode(const Item_Type& the_data, AVLNode<Item_Type>* left = NULL, AVLNode<Item_Type>* right = NULL) : data(the_data), left(left), right(right), right_height(0), left_height(0) {}
// Destructor (to avoid warning message)
virtual ~AVLNode() {}
int balance(){ return right_height - left_height; }
int height(){
return right_height > left_height ? right_height : left_height; }
void update_right_height(){
if (right != NULL)
right_height = 1 + right->height();
else
right_height = 0;
}
void update_left_height(){
if (left != NULL)
left_height = 1 + left->height();
else
left_height = 0;
}
// to_string
virtual std::string to_string() const {
std::ostringstream os;
os << "data : " << this->data;
return os.str();
}
}; // End AVLNode
#endif
Finally, the class I created, the Folder class:
#pragma once
#include <string>
#include "AVL_Tree.h"
using namespace std;
class Folder
{
private:
string name;
int size;
public:
Folder()
{
name = "";
size = 0;
}
Folder(string Name, int Size)
{
name = Name;
size = Size;
}
int getSize()
{
return size;
}
string getName()
{
return name;
}
void setSize(int Size)
{
size = Size;
}
void setName(string Name)
{
name = Name;
}
};
The error only occurs when I try to do
AVL_Tree<Folder> folderTree;
it works for other types, such as string, int, char, etc. Any help would be greatly appreciated. As far as I know, we are not supposed to modify the instructor's code.
Your class Folder should be "comparable", it means the following code should compile Folder a,b; bool result = (a<b);
To achieve this, you can define the comparison operator withing your class
bool operator< (const Folder & other) const
{
return size < other.size || (size == other.size && name < other.name);
}
Alternatively you can define a global comparison operator bool operator< (const Folder & lhs, const Folder & rhs).

How to check if a binary tree remains AVL and maintain it?

I'm having some trouble with the creation of an AVL tree structure in C++ for a university project. So far, I managed to make simple add and delete functions, but here comes the problem! I 've seen some codes here where the checks are made in the add function directly, but I didn't want to copy the code. Is there a way to create a seperate function which does exactly this work? The thing I can't make work is how to make the program understand in which rotation case I have to go.
My code so far is this:
struct node
{
unsigned int target;
struct node *left;
struct node *right;
};
int ClassInvertedIndex::Height(struct node *toCheck)
{
int left, right;
if(toCheck == NULL)
return 0;
left = Height(toCheck->left);
right = Height(toCheck->right);
if(left > right)
return left+1;
else
return right+1;
}
void ClassInvertedIndex::maintainAVL(struct node *toCheck)
{
if(Height(toCheck->left)-Height(toCheck->right) == 2); //Left subtree problem.
if(Height(toCheck->right)-Height(toCheck->left) == 2); //Right subtree problem.
}
bool ClassInvertedIndex::addNode(unsigned int x)
{
return insideAdd(data, x);
}
bool ClassInvertedIndex::insideAdd(struct node *toAdd, unsigned int x)
{
if(toAdd == NULL)
{
toAdd = new struct node;
if(toAdd == NULL)
{
cout << "Could not allocate memory.";
return false;
}
toAdd->left = NULL;
toAdd->right = NULL;
toAdd->target = x;
return true;
}
else if(x < toAdd->target)
{
bool result;
result = insideAdd(toAdd->left, x);
if(result)
{
//maintainAVL(toAdd);
}
return result;
}
else if(x > toAdd->target)
{
bool result;
result = insideAdd(toAdd->right, x);
if(result)
{
//maintainAVL(toAdd);
}
return result;
}
else //x already exists.
{
return false;
}
}
So, in the maintainAVL method, what should I do to decide what rotation I need?