red-black tree invalid conversion - c++

I am having trouble getting past the initialization of the red black tree. Whenever I compile I get the following error.
redBlackTree.h:81:28: error: invalid conversion from ‘long int’ to ‘nodeColor’ [-fpermissive]
nodeType<myType> *x = new nodeType<myType>;
^
redBlackTree.h:10:8: error: invalid conversion from ‘long int’ to ‘nodeColor’ [-fpermissive]
struct nodeType
^
redBlackTree.h:81:28: note: synthesized method ‘nodeType<int>::nodeType()’ first required here
nodeType<myType> *x = new nodeType<myType>;
I am also having trouble searching the tree to make sure a value is not already inside the tree. The current method I can think of it this but I am still getting duplicate results inside of my tree.
if(nd != NULL)
{
if(nd->keyValue == x)
return true;
return ((search(x, nd->right)) || (search(x, nd->left)));
}
return false;
It is under the insertion function. Could it be how I am declaring my variables? We are supposed to follow a certain template and it says to make x a new nodeType but am not able to. Deleting it causes the program to have a seg fault.
#ifndef REDBLACKTREE_H
#define REDBLACKTREE_H
#include <iostream>
#include <sstream>
using namespace std;
enum nodeColor { RED, BLACK };
template<class myType>
struct nodeType
{
myType keyValue = keyValue;
nodeColor color = NULL;
nodeType *left = NULL;
nodeType *right = NULL;
nodeType *parent = NULL;
};
template <class myType>
class redBlackTree
{
public:
redBlackTree(){};
~redBlackTree();
void destroyTree();
unsigned int countNodes() const;
unsigned int height() const;
void printTree() const;
void insert(myType);
bool search(myType);
private:
nodeType<myType> *root = NULL;
bool search(myType, nodeType<myType> *);
void destroyTree(nodeType<myType> *);
unsigned int countNodes(nodeType<myType> *) const;
unsigned int height(nodeType<myType> *) const;
void printTree(nodeType<myType> *) const;
void rightRotate(nodeType<myType> *);
void leftRotate(nodeType<myType> *);
};
//template <class myType>
//redBlackTree<myType>::redBlackTree():root(NULL)
//{
//};
template <class myType>
redBlackTree<myType>::~redBlackTree()
{
destroyTree();
}
template <class myType>
void redBlackTree<myType>::destroyTree()
{
destroyTree(root);
};
template <class myType>
unsigned int redBlackTree<myType>::countNodes() const
{
return countNodes(root);
};
template <class myType>
unsigned int redBlackTree<myType>::height() const
{
return height(root);
};
template <class myType>
void redBlackTree<myType>::printTree() const
{
printTree(root);
};
template <class myType>
void redBlackTree<myType>::insert(myType value)
{
if(search(value))
return;
nodeType<myType> *x = new nodeType<myType>;
x->right = NULL;
x->left = NULL;
x->parent = NULL;
x->keyValue = value;
x->color = RED;
if(root == NULL)
{
root = x;
x->color = BLACK;
return;
}
nodeType<myType> *curr = root;
if(curr->keyValue > x->keyValue)
{
curr->left = x;
x->parent = curr;
x->color = RED;
}
else
{
curr->right = x;
x->parent = curr;
x->color = RED;
}
while(x != root && x->parent->color == RED)
{
if(x->parent == x->parent->parent->left)
{
if(x->parent->parent->right != NULL && x->parent->parent->color == RED)
{
x->parent->color = BLACK;
x->parent->parent->right->color = BLACK;
x->parent->parent->color = RED;
x = x->parent->parent;
}
else
{
if(x == x->parent->right)
{
x = x->parent;
leftRotate(x);
}
x->parent->color = BLACK;
x->parent->parent->color = RED;
rightRotate(x->parent->parent);
}
}
else
{
if(x->parent->parent->left != NULL && x->parent->parent->color == RED)
{
x->parent->color = BLACK;
x->parent->parent->left->color = BLACK;
x->parent->parent->color = RED;
x = x->parent->parent;
}
else
{
if(x == x->parent->right)
{
x = x->parent;
rightRotate(x);
}
x->parent->color = BLACK;
x->parent->parent->color = RED;
leftRotate(x->parent->parent);
}
}
if(x == root)
x->color = BLACK;
}
};
template <class myType>
bool redBlackTree<myType>::search(myType x)
{
search(x, root);
};
template <class myType>
bool redBlackTree<myType>::search(myType x, nodeType<myType> *nd)
{
if(nd == NULL)
return 0;
search(x, nd->left);
search(x, nd->right);
if(nd->keyValue == x)
return true;
else
return false;
};
template <class myType>
void redBlackTree<myType>::destroyTree(nodeType<myType> *node)
{
if(node==NULL)
return;
destroyTree(node->left);
destroyTree(node->right);
delete node;
};
template <class myType>
unsigned int redBlackTree<myType>::countNodes(nodeType<myType> *nd) const
{
if(nd==NULL)
return 0;
return (countNodes(nd->left) + countNodes(nd->right) + 1);
};
template <class myType>
unsigned int redBlackTree<myType>::height(nodeType<myType> *nd) const
{
int leftHeight = 0;
int rightHeight = 0;
if(nd==NULL)
return 1;
leftHeight = leftHeight + height(nd->left);
rightHeight = rightHeight + height(nd->right);
if(leftHeight == rightHeight)
return leftHeight;
else if(leftHeight > rightHeight)
return leftHeight;
else
return rightHeight;
};
template <class myType>
void redBlackTree<myType>::printTree(nodeType<myType> *nd) const
{
if(nd == NULL)
return;
printTree(nd->left);
cout << nd->keyValue;
printTree(nd->right);
cout << nd->keyValue;
};
template <class myType>
void redBlackTree<myType>::rightRotate(nodeType<myType> *y)
{
nodeType<myType> *x = y->left;
x->left = x->right;
if(x->right != NULL)
x->right->parent = y;
x->parent = y->parent;
if(x->parent == NULL)
root = x;
else if(y == y->parent->left)
y->parent->left = x;
else
y->parent->right = x;
x->right = y;
y->parent = x;
};
template <class myType>
void redBlackTree<myType>::leftRotate(nodeType<myType> *x)
{
nodeType<myType> *y = y->right;
x->right = y->left;
if(x->right != NULL)
root = y;
else if(x == x->parent->left)
x->parent->left = y;
else
x->parent->right = y;
x->left = x;
x->parent = y;
};
#endif

The problem is caused by the line:
nodeColor color = NULL;
NULL is not a valid value for color. Use a value that is valid, such as:
nodeColor color = RED;
Also, the line
myType keyValue = keyValue;
is going to be a problem. It initializes keyValue with the uninitialized value of keyValue.Make the RHS of that line something more appropriate, such as:
myType keyValue = {};
You are missing a return in the first search function.
template <class myType>
bool redBlackTree<myType>::search(myType x)
{
return search(x, root);
// ^^
}
You don't need ; at the end of member function definition. You have them in some of the function definitions. You should remove them.

Related

Red Black Tree implementation using CLRS method. Having trouble spotting my errors

I'm having trouble implementing the CLRS method for a Red Black Tree. I'm not able to successful insert and I don't know what I'm doing wrong. I struggle with pointers and it's a topic I'm trying to learn more about (I'm buying a book on Amazon this weekend to learn more). Please help me pin point errors. I'm not receiving error messages, but my code won't run past my RBTInsert function, so I know it's getting stuck there. I call RBT Insert in another function that's not shown, but I didn't show it because I'm convinced my errors are in my pointers and nodes.
enum Color {RED, BLACK};
template <typename T>
struct Node
{
T data;
bool color;
Node<T>* left = nullptr;
Node<T>* right = nullptr;
Node<T>* p = nullptr; //p is parent
}
template <typename T>
class RBT
{
private:
Node<T>* root;
void RotateLeft(Node<T>*, Node<T>*);
void RotateRight(Node<T>*, Node<T>*);
void RBTFixUp(Node<T>*, Node<T>*);
void MakeEmpty(Node<T>* root);
public:
RBT(): root(nullptr){}
~RBT();
void RBTInsert(Node<T>* &root, T data);
};
template <typename T>
void RBT<T>::MakeEmpty(Node<T>* root)
{
while (root != nullptr)
{
delete root;
MakeEmpty(root->left);
MakeEmpty(root->right);
}
}
template <typename T>
RBT<T>::~RBT()
{
MakeEmpty(root);
}
template <typename T>
void RBT<T>::RotateLeft(Node<T>* root, Node<T>* x)
{
Node<T>* y = x->right;
x->right = y->left;
if (y->left != nullptr)
y->left->p = x;
y->p = x->p;
if (x->p == nullptr)
root = y;
else if (x == x->p->left)
x->p->left = y;
else
x->p->right = y;
y->left = x;
x->p = y;
}
template <typename T>
void RBT<T>::RotateRight(Node<T>* root, Node<T>* x)
{
Node<T>* y = x->left;
x->left = y->right;
if (y->right != nullptr)
y->right->p = x;
y->p = x->p;
if (x->p == nullptr)
root = y;
else if (x == x->p->right)
x->p->right = y;
else
x->p->left = y;
y->right= x;
x->p = y;
}
template <typename T>
void RBT<T>::RBTFixUp(Node<T>* root, Node<T>* z)
{
while (z->p->color == RED)
{
if (z->p == z->p->p->left)
{
Node<T>* y = z->p->p->right;
if(y->color == RED)
{
z->p->color = BLACK;
y->color = BLACK;
z->p->p->color = RED;
z = z->p->p;
}else if (z == z->p->right)
{
z = z->p;
RotateLeft(root,z);
}
}else
{
Node<T>* y = z->p->p->left;
if(y->color == RED)
{
z->p->color = BLACK;
y->color = BLACK;
z->p->p->color = RED;
z = z->p->p;
}else if (z == z->p->left)
{
z = z->p;
RotateRight(root,z);
}
}
}
}
template <typename T>
void RBT<T>::RBTInsert(Node<T>* &root, T data)
{
Node<T>* z = nullptr;
z->data = data;
Node<T>* y = nullptr;
Node<T>* x = nullptr;
while (x != nullptr)
{
y = x;
if (z->data < x->data)
x = x->left;
else
x = x->right;
}
z->p = y;
if (y == nullptr)
root = z;
else if (z->data < y->data)
y->left = z;
else
y->right = z;
z->left = nullptr;
z->right = nullptr;
z->color = RED;
RBTFixUp(root,z);
}

Faulty avltree implementation c++

this is my current avltree implementation, avltree.h:
#pragma once
#include <math.h>
#include <algorithm>
#include <iostream>
namespace avltree {
template <class T>
struct node {
static node * null_node;
node *left = null_node;
node *right = null_node;
node *parent = null_node;
int height = 0;
T value;
node(T value) :value(value) {}
node(T value, int height) :height(height), value(value) {}
};
template <class T>
node<T>* node<T>::null_node = new node(0, -1);
template <class T>
struct avltree {
public:
node<T> *root;
avltree(T value);
node<T> *insert(T value);
void print(void);
void print_with_height(void);
private:
node<T> *insert(T value, node<T> *x);
node<T> *left_rotate(node<T> *x);
node<T> *right_rotate(node<T> *x);
void retrace(node<T> *n);
void update_root();
void print(node<T> *n);
void print(node<T> *n, int depth);
void update_height(node<T> *n);
};
template <class T>
avltree<T>::avltree(T value) :root(new node<T>(value)) { }
template <class T>
node<T> *avltree<T>::insert(T value) {
auto n = insert(value, root);
update_root();
return n;
}
template <class T>
void avltree<T>::retrace(node<T> *n) {
while (n != node<T>::null_node) {
update_height(n);
if (n->left->height - n->right->height > 1) {
if (n->left->left->height >= n->left->right->height) {
right_rotate(n);
}
else {
left_rotate(n);
right_rotate(n);
}
}
else
if (n->right->height - n->left->height > 1) {
if (n->right->right->height >= n->right->left->height) {
left_rotate(n);
}
else {
right_rotate(n);
left_rotate(n);
}
}
n = n->parent;
}
}
template <class T>
node<T> *avltree<T>::insert(T value, node<T> *n) {
if (n->value > value) {
if (n->left != node<T>::null_node) {
n->left->height++;
insert(value, n->left);
}
else {
auto new_node = new node<T>(value);
n->left = new_node;
new_node->parent = n;
retrace(n);
return new_node;
}
}
if (n->value < value) {
if (n->right != node<T>::null_node) {
n->right->height++;
insert(value, n->right);
}
else {
auto new_node = new node<T>(value);
n->right = new_node;
new_node->parent = n;
retrace(n);
return new_node;
}
}
update_height(n);
return n;
}
template <class T>
node<T> *avltree<T>::left_rotate(node<T> *x) {
node<T> *y = x->right;
if (y == node<T>::null_node) {
return node<T>::null_node;
}
y->parent = x->parent;
if (x->parent->right == x) {
x->parent->right = y;
}
else {
x->parent->left = y;
}
y->left = x;
x->parent = y;
x->right = y->left;
x->right->parent = x;
update_height(x);
update_height(y);
return x;
}
template <class T>
node<T> *avltree<T>::right_rotate(node<T> *x) {
node<T> *y = x->left;
if (y == node<T>::null_node) {
return node<T>::null_node;
}
y->parent = x->parent;
if (x->parent->right == x) {
x->parent->right = y;
}
else {
x->parent->left = y;
}
y->right = x;
x->parent = y;
x->left = y->right;
x->left->parent = x;
update_height(x);
update_height(y);
return x;
}
template <class T>
void avltree<T>::update_root() {
auto n = root, last = root;
while (n != node<T>::null_node) {
last = n;
n = n->parent;
}
root = last;
}
template <class T>
void avltree<T>::print(void) {
print(root);
cout << endl;
}
template <class T>
void avltree<T>::print(node<T> *n) {
if (n->left != node<T>::null_node) {
print(n->left);
}
cout << n->value << " ";
if (n->right != node<T>::null_node) {
print(n->right);
}
}
template <class T>
void avltree<T>::print(node<T> *n, int height) {
if (n->left != node<T>::null_node) {
print(n->left, height);
}
if (n->height == height) {
std::cout << n->value << ", ";
}
if (n->right != node<T>::null_node) {
print(n->right, height);
}
}
template <class T>
void avltree<T>::print_with_height(void) {
int height = root->height;
for (int height = root->height; height >= 0; height--) {
std::cout << "height = " << height << "\t:";
print(root, height);
std::cout << std::endl;
}
std::cout << std::endl;
}
template <class T>
void avltree<T>::update_height(node<T> *n) {
n->height = std::max(n->left->height, n->right->height) + 1;
}
}
And the following is main file:
#include "stdafx.h"
#include "avltree.h"
int main()
{
avltree::avltree<int> tree(1);
for (int i = 2; i < 128; i++) {
tree.insert(i);
}
tree.print_with_height();
return 0;
}
The problem with above code is that at iteration 124 it will generate an infinite loop inside retrace call in insert. Basically, the nodes will keep being rotated in such a way that root node cannot be reached (resulting in an infinite loop). I have checked the trivial examples (for a few nodes) and they work. Everything for a run is provided, I would appreciate if someone with experience in avltrees could take their time and run this program, perhaps finding out what goes wrong inside retrace/rotations.
Getting an infinite loop like that indicates a likely problem with your rotate functions. A quick look at left_rotate shows
y->left = x;
x->parent = y;
x->right = y->left;
What is y->left in that last assignment? x, so what you're really is x->right = x. This is clearly a problem that needs to be fixed.
A similar problem exists in right_rotate.

errorC2512 and error C2955 using C++ template

#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.

Red-Black Tree Insertion CLRS

The algorithm described in CLRS 3 ed. looks wrong. I tried implement but the insertion not works fine.
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <ctime>
#include <vector>
#include <algorithm>
using namespace std;
const char BLACK = 'B';
const char RED = 'R';
template <class T>
class Node{
public:
Node *left;
Node *right;
Node *parent;
char color;
T key;
Node(T x){
this->left = NULL;
this->right = NULL;
this->parent = NULL;
this->key = x;
this->color = RED;
};
virtual ~Node(){};
};
template <class T>
class RedBlackTree{
private:
int ammount;
int h;
int lastAmmount;
Node<T> *root;
Node<T> *NIL;
void destroy_node(Node<T> *&node);
Node<T> *remove_node(Node<T> *&node, T x); // not imeplemented yet
Node<T> *search_node(Node<T> *&node, T x); // not imeplemented yet
void printInfo(Node<T> *&x);
void printInOrder_node(Node<T> *&node);
void printInLevel_node(Node<T> *&node, int level);
int calculeHeight(Node<T> *&node);
void rotateLeft(Node<T> *&x);
void rotateRight(Node<T> *&y);
void insertFixUp(Node<T> *&x);
public:
RedBlackTree();
virtual ~RedBlackTree();
void destroy();
void insert(T x);
void remove(T x); // not imeplemented yet
Node<T> *search(T x); // not implemented yet
int height();
void printInOrder();
void printInLevel();
};
template <class T>
RedBlackTree<T>::RedBlackTree(){
this->ammount = 0;
this->lastAmmount = -1;
this->h = 0;
this->NIL = new Node<T>(-1);
this->NIL->color = BLACK;
this->NIL->left = this->NIL->right = this->NIL->parent = this->NIL;
this->root = this->NIL;
this->root->color = BLACK;
}
template <class T>
RedBlackTree<T>::~RedBlackTree(){
delete this->root;
}
template <class T>
void RedBlackTree<T>::destroy_node(Node<T> *&node){
if(node != NULL){
this->destroy(node->left);
this->destroy(node->right);
delete node;
}
}
template <class T>
void RedBlackTree<T>::destroy(){
this->destroy_node(this->root);
}
// RB methods
template <class T>
void RedBlackTree<T>::rotateLeft(Node<T> *&x){
Node<T> *y = x->right;
x->right = y->left;
if(y->left != this->NIL)
y->left->parent = x;
y->parent = x->parent;
if(x->parent == this->NIL)
this->root = y;
else if(x == x->parent->left)
x->parent->left = y;
else
x->parent->right = y;
y->left = x;
x->parent = y;
}
template <class T>
void RedBlackTree<T>::rotateRight(Node<T> *&y){
Node<T> *x = y->left;
y->left = x->right;
if(x->right != this->NIL)
x->right->parent = y;
x->parent = y->parent;
if(y->parent == this->NIL)
this->root = x;
else if(y == y->parent->left)
y->parent->left = x;
else
y->parent->right = x;
x->right = y;
y->parent = x;
}
template <class T>
void RedBlackTree<T>::insertFixUp(Node<T> *&z){
Node<T> *y;
while(z != this->root and z->parent->color == RED){
if(z->parent == z->parent->parent->left){
y = z->parent->parent->right;
if(y->color == RED){
z->parent->color = BLACK;
y->color = BLACK;
z->parent->parent->color = RED;
z = z->parent->parent;
}
else{
if(z == z->parent->right){
z = z->parent;
this->rotateLeft(z);
}
z->parent->color = BLACK;
z->parent->parent->color = RED;
this->rotateRight(z->parent->parent);
}
}
else{
y = z->parent->parent->left;
if(y->color == RED){
z->parent->color = BLACK;
y->color = BLACK;
z->parent->parent->color = RED;
z = z->parent->parent;
}
else{
if(z == z->parent->left){
z = z->parent;
this->rotateRight(z);
}
z->parent->color = BLACK;
z->parent->parent->color = RED;
this->rotateLeft(z->parent->parent);
}
}
}
this->root->color = BLACK;
}
template <class T>
void RedBlackTree<T>::insert(T val){
Node<T> *z = new Node<T>(val);
Node<T> *x = this->root;
Node<T> *y = this->NIL;
while(x != this->NIL){
y = x;
if(z->key < x->key)
x = x->left;
else
x = x->right;
}
z->parent = y;
if(y == this->NIL)
this->root = z;
else if(z->key < y->key)
y->left = z;
else
y->right = z;
z->left = this->NIL;
z->right = this->NIL;
z->color = RED;
this->insertFixUp(z);
}
template <class T>
int RedBlackTree<T>::height(){
if(this->lastAmmount == this->ammount)
return this->h;
this->h = this->calculeHeight(this->root);
this->lastAmmount = this->ammount;
return this->h;
}
template <class T>
int RedBlackTree<T>::calculeHeight(Node<T> *&node){
if(node == this->NIL)
return 0;
int l_h = this->calculeHeight(node->left);
int r_h = this->calculeHeight(node->right);
if(l_h > r_h)
return l_h+1;
return r_h+1;
}
template <class T>
void RedBlackTree<T>::printInfo(Node<T> *&x){
cout << "key=";
cout << x->key;
cout << " l->key=";
if( x->left == this->NIL)
cout << "N";
else
cout << x->left->key;
cout << " r->key=";
if( x->right == this->NIL)
cout << "N";
else
cout << x->right->key;
cout << " p->key=";
if( x->parent == this->NIL)
cout << "N";
else
cout << x->parent->key;
cout << " color=" << x->color << endl;
}
template <class T>
void RedBlackTree<T>::printInOrder_node(Node<T> *&node){
if(node != this->NIL){
this->printInOrder_node(node->left);
//cout << " " << node->key;
this->printInfo(node);
this->printInOrder_node(node->right);
}
}
template <class T>
void RedBlackTree<T>::printInOrder(){
this->printInOrder_node(this->root);
}
template <class T>
void RedBlackTree<T>::printInLevel(){
int h = this->height();
for(int i=1; i<=h; i++)
this->printInLevel_node(this->root, i);
}
template <class T>
void RedBlackTree<T>::printInLevel_node(Node<T> *&node, int level){
if(node == this->NIL)
return;
if(level == 1)
this->printInfo(node); //cout << node->key << " ";
else if(level > 1){
this->printInLevel_node(node->left, level-1);
this->printInLevel_node(node->right, level-1);
}
}
int main(){
RedBlackTree<int> *bt = new RedBlackTree<int>();
int v[9] = {11, 2, 14, 1, 7, 15, 5, 8, 4};
for(int i=0; i<9; i++){
int x = v[i];
cout << x << " ";
bt->insert(x);
}
cout << endl;
cout << "In Level:" << endl;
bt->printInLevel();
cout << endl;
delete bt;
return 0;
}
I tried to find some others explanations in previous topics, but not seems to work.
This code is basically equals the pseudocode of the book. The expected result for the main example is in level:
7
/ \
2 11
/ \ / \
1 5 8 14
/ \
4 15
So, what's wrong?
Thanks!
Consider what happens when you add the second node. You start with this:
11 (black)
then add the new node:
11 (black)
/
2 (red)
then then try to fix it up:
template <class T>
void RedBlackTree<T>::insertFixUp(Node<T> *&z){
Node<T> *y;
while(z != this->root and z->parent->color == RED){
...
}
this->root->color = BLACK;
}
Note that since 11 is black to begin with, control never enters the loop, so the call to insertFixUp does nothing. So you're left with a tree with a red leaf, which is not a valid red-black tree. After that, if your code expects to be working on a valid red-black tree, it's liable to go wrong.
There may be other bugs, but you should try to get the two-node tree working before you attempt to add a third node.

C++ - Creating Binary Search Tree Class, one Node disappears after rotate

I am trying to create a custom Binary Search Tree, and I have everything done except for the rotate function, which seems to be not moving a node over. The rotate function only gets called when a node is searched and found, and if the node has a right child. For simplicity I will only add the functions that are used in this, to make it shorter:
#include <iostream>
using namespace std;
template <typename T>
class MRBST {
public:
MRBST();
~MRBST();
void push(const T &);
bool search(const T &);
void PrintPreorder();
private:
struct Node {
T data;
Node *left;
Node *right;
Node (const T & theData, Node *lt, Node *rt)
: data(theData), left(lt), right(rt) {}
};
Node *root;
void push(const T &, Node * &) const;
void remove(const T &, Node * &) const;
Node* findMin(Node *t) const {
if (t == NULL) {
return NULL;
}
if (t->left == NULL) {
return t;
}
return findMin(t->left);
}
void preorder(Node * &);
bool search(const T &, Node *);
Node* findNode(const T & x, Node * t) {
if (t == NULL) {
return NULL;
}
if (x < t->data) {
return findNode(x, t->left);
} else if (x > t->data) {
return findNode(x, t->right);
} else if (x == t->data) {
return t;
}
return NULL;
}
void rotate(Node *);
};
template <typename T>
void MRBST<T>::PrintPreorder() {
preorder(root);
cout << endl;
}
template <typename T>
void MRBST<T>::preorder(Node * & t) {
if (t != NULL) {
cout << t->data << endl;
preorder(t->left);
preorder(t->right);
}
}
template <typename T>
bool MRBST<T>::search(const T & x) {
if (search(x, root)) {
Node *temp = findNode(x, root);
rotate(temp);
return true;
} else {
return false;
}
}
template <typename T>
void MRBST<T>::rotate(Node * k1) {
if (k1->right == NULL) {
return;
} else {
Node *temp = k1->right;
k1->right = temp->left;
temp->left = k1;
}
}
template <typename T>
bool MRBST<T>::search(const T & x, Node *t) {
if (t == NULL) {
return false;
} else if (x < t->data) {
return search(x, t->left);
} else if (x > t->data) {
return search(x, t->right);
} else {
return true;
}
}
I have a simple testing file that just adds some numbers to the tree, and then searches, followed by a print out in Preordering.
#include <iostream>
#include "MRBST.h"
using namespace std;
int main() {
MRBST<int> binaryTree;
binaryTree.push(5);
binaryTree.push(20);
binaryTree.push(3);
binaryTree.push(3);
binaryTree.push(4);
binaryTree.push(22);
binaryTree.push(17);
binaryTree.push(18);
binaryTree.push(8);
binaryTree.push(9);
binaryTree.push(1);
binaryTree.PrintPreorder();
cout << endl;
binaryTree.search(17);
binaryTree.PrintPreorder();
cout << endl;
}
With the output looking a something like this:
5
3
1
4
20
17
8
9
18
22
5
3
1
4
20
17
8
9
22
If anyone could give some insight into what is going wrong with my rotate function, that would be a great help.
Why are you doing rotate on search? It should be read-only.
You're losing the node because of that.
Look at your rotate:
Node *temp = k1->right;
k1->right = temp->left;
temp->left = k1;
Assume k1=x has right=y and left=z, look step by step:
Node *temp = k1->right;
temp =k1->right = y, k1 = x, k1->left = z
k1->right = temp->left;
k1->right = ?, k1->left = z, temp = y
temp->left = k1;
k1->right = ?, k1->left = z, temp->left = x.
Now - where did Y go? You lost it.
Look closely at your rotate() function, step by step, to see whether it does what you want it to do or not.