Faulty avltree implementation c++ - 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.

Related

AVL Tree Nodes (Print)

I'm currently working through AVL trees and am curious why the output (pre order traversal) is only showing two levels of indentation, as if one of the second order nodes is pointing to three separate 3rd level node. I'm note sure if this is an issue with my print function, or the actual code.
#include <iostream>
#include <list>
#include <vector>
#include <iomanip>
using namespace std;
template <class T>
class BST;
template <class T>
class BSTNode{
T data;
BSTNode<T>* parent;
BSTNode<T>* left;
BSTNode<T>* right;
int height;
public:
BSTNode(T data = T(), BSTNode<T>* parent = nullptr, BSTNode<T>* left = nullptr,
BSTNode<T>* right = nullptr, int height = 0) : data(data), parent(parent), left(left), right(right), height(height){}
friend class BST<T>;
int getSize() const;
};
template <class T>
class BST{
public:
BSTNode<T>* root = nullptr;
BST() {}
~BST();
BST(const BST& rhs) {*this = rhs;};
BST& operator=(const BST& rhs);
void printPreOrder(BSTNode<T>* p, int indent);
void insert(T item, BSTNode<T> * & node);
void remove(BSTNode<T>*& temp); //pass pointer by reference because we will be changing the pointer
void clear(BSTNode<T>*& root); //clears the entire tree;
BST<T>* clone(BSTNode<T>* start);
void rotateRight(BSTNode<T> * & node); //rotate the left child (the left child becomes the parent and parent becomes the right child)
void rotateLeft(BSTNode<T> * & node); //rotate the right child (the right child becomes the parent and the parent becomes the left child)
void doubleRotateRight(BSTNode<T> *& node); //same result as rotate right
void doubleRotateLeft(BSTNode<T> *& node); //same result as rotate left
int height(BSTNode<T> * node); //return height
void balance(BSTNode<T> * &node);
};
template <class T>
int BSTNode<T>::getSize() const {
int count = 1;
if(left != nullptr){
count += left->getSize();
};
if(right != nullptr){
count += right->getSize();
};
return count;
}
template <class T>
void BST<T>::printPreOrder(BSTNode<T>* p, int indent){
if(p) {
if (indent) {
std::cout << std::setw(indent) << '\t';
}
cout<< p->data << "\n ";
if(p->left) printPreOrder(p->left, indent+2);
if(p->right) printPreOrder(p->right, indent+2);
}
}
template <class T>
void BST<T>::insert(T item, BSTNode<T> * & node){
if(!node){
node = new BSTNode<T>(item);
}
else if(item < node->data){
insert(item, node->left);
}
else{
insert(item, node->right);
}
balance(node);
}
template <class T>
void BST<T>::remove(BSTNode<T>*& temp){
if(temp->left == nullptr && temp->right == nullptr){
if(temp->parent == nullptr){
root = nullptr;
}
else if(temp->parent->left == temp){
temp->parent->left = nullptr;
}
else{
temp->parent->right = nullptr;
}
delete temp;
}
else if(temp->left == nullptr){ //promote right
BSTNode<T>* toDelete = temp->right;
temp->data = toDelete->data;
temp->left = toDelete->left;
temp->right = toDelete->right;
if(temp->left){
temp->left->parent = temp->left;
}
if(temp->right){
temp->right->parent = temp;
}
delete toDelete;
}
else if(temp->right == nullptr){ //promote left
BSTNode<T>* toDelete = temp->left;
temp->data = toDelete->data;
temp->left = toDelete->left;
temp->right = toDelete->right;
if(temp->left){
temp->left->parent = temp->left;
}
if(temp->right){
temp->right->parent = temp;
}
delete toDelete;
}
else{
BSTNode<T>* maxOfLeft = temp->left;
while(maxOfLeft){
maxOfLeft = maxOfLeft->right;
}
temp->data = maxOfLeft->data;
remove(maxOfLeft);
}
balance(temp);
}
template <class T>
void BST<T>::clear(BSTNode<T>*& root) {
if (root) {
if (root->left) {
clear(root->left);
}
if (root->right) {
clear(root->right);
}
delete root;
}
root = nullptr;
};
template <class T>
BST<T>::~BST(){
clear(root);
}
template <class T>
BST<T>* BST<T>::clone(BSTNode<T>* start){
if(!start){
return nullptr;
}
else{
return new BSTNode<T>(start->data, clone(start->left), clone(start->right));
}
}
template <class T>
BST<T>& BST<T>::operator=(const BST<T>& rhs){
if(this == &rhs){
return *this;
}
clear(root);
root = clone(rhs.root);
return *this;
}
template <class T>
void BST<T>::rotateRight(BSTNode<T> * & node){
BSTNode<T> * newParent = node->left;
node->left = newParent->right;
newParent->right = node;
node->height = max(height(node->right),height(node->left)) + 1;
newParent->height = max(height(newParent->left), node->height) + 1;
node = newParent; //set new root (we can't access newParent outside of this function!)
}
template <class T>
void BST<T>::rotateLeft(BSTNode<T> * & node){
BSTNode<T> * newParent = node->right;
node->right = newParent->left;
newParent->left = node;
node->height = max(height(node->right), height(node->left)) + 1;
newParent->height = max(height(newParent->right), node->height) + 1;
node = newParent; //set new root (we can't access newParent outside of this function!)
}
template <class T>
int BST<T>::height(BSTNode<T> *node){
if(node){
return node->height;
};
return -1;
}
template <class T>
void BST<T>::doubleRotateRight(BSTNode<T> * &node){
rotateLeft(node->left);
rotateRight(node);
}
template<class T>
void BST<T>::doubleRotateLeft(BSTNode<T> * &node){
rotateRight(node->right);
rotateLeft(node);
}
template<class T>
void BST<T>::balance(BSTNode<T> * &node){
if(!node){
return;
}
if(height(node->left) > height(node->right) + 1){
if(height(node->left->left) >= height(node->left->right)){
rotateRight(node);
}
else{
doubleRotateRight(node);
};
};
if(height(node->right) > height(node->left) + 1){
if(height(node->right->right) >= height(node->right->left)){
rotateLeft(node);
}
else{
doubleRotateLeft(node);
}
}
node->height = max(height(node->right), height(node->left)) + 1;
}
int main() {
vector<int>data = {5, 3, 4, 2, 1, 2, 6, 7};
BST<int> test;
for(int r : data){
test.insert(r, test.root);
}
test.printPreOrder(test.root,0);
cout << endl;
return 0;
}
Here is the output I am getting:
3
2
1
2
5
4
6
7
From my understanding, I should be getting the following output:
3
2
1
2
5
4
6
7
Don't use tabs.
Consider this example:
#include <iostream>
#include <iomanip>
int main() {
for (int indent=0;indent<5;++indent) {
if (indent) {
std::cout << std::setw(indent) << "\t" << "tabs" << "\n";
std::cout << std::setw(indent) << " " << "spaces" << "\n";
}
}
}
Possible output is:
tabs
spaces
tabs
spaces
tabs
spaces
tabs
spaces

Calling a method of a abstract class inside of a linked list fails

I wrote a Class called cube which holds a double linked list which should hold objects of a abstract class called Animation and has a method to add animations . It looks liket his:
class CubeLib
{
protected:
//some more variables
LinkedList<Animation*> animations; //a list of animations
public:
inline void addAnimation(Animation* a){
animations.add(a);
};
}
The interface:
class Animation
{
public:
virtual void update(short delta) = 0;
};
Inside of the ino of the arduino project i init the CubeLib and the Animation in global and inside of the setup i add them to the list:
CubeLib cube;
Sinus* sinus_ani =new Sinus(&cube); // if not like this it stucks at setup?!
void setup()
{
cube.addAnimation(sinus_ani);
}
Inside of a method called render i call the current Animations update function.
inline void CubeLib::update(short delta)
{
if (animations.size() != -1){ //if its not empty
animations[current_Animation]->update(delta);
}
}
But in this case it does happen nothing. The update of the Sinus does not get called.
Last but not least here is my double linked list. (I tested it but maybe there is some issue with it?)
template <typename T>
class LinkedList
{
protected:
private:
struct Node
{
Node* prev;
Node* next;
T value;
};
Node* last;
Node* first;
byte count;
public:
LinkedList()
{
count = -1; //empty
};
~LinkedList()
{
if (count > -1){
clear();
}
};
/** adds to list*/
inline void add(T t);
/**removes the thing at index*/
inline T remove(int index);
/** Returns NULL(ptr) if index is out of range or item not found somehow*/
inline T get(int index);
inline void clear();
/**Returns the first obj*/
inline T getFirst();
/**Returns the last obj*/
inline T getLast();
/**Returns the current size. If -1 its empty!*/
inline int size(){
return count;
};
T operator[](const int i)
{
return get(i);
};
};
template <typename T>
inline void LinkedList<T>::add(T t){
Node* n = new Node();
n->value = t;
if (count > -1)
{
n->next = first;
n->prev = last;
last->next = n;
last = n;
count++;
}
else if (count == -1)//first element
{
first = n;
first->next = n;
first->prev = n;
last = n;
last->next = n;
last->prev = n;
count++;
}
}
template <typename T>
inline T LinkedList<T>::remove(int index){
if (index <= count)
{
Node* n = last;
for (int i = 0; i <= index; i++)
{
n = n->next;
}
n->prev->next = n->next;
n->next->prev = n->prev;
count--;
return n->value; //return the value of that node
}
}
template <typename T>
inline T LinkedList<T>::get(int index){
if (index <= count && index > -1)
{
Node* n = first;
int i = 0;
while (i < index)
{
n = n->next;
i++;
}
return n->value;
}
return NULL;
}
template <typename T>
inline void LinkedList<T>::clear()
{
Node* n = first;
while (count > 0)
{
Node* toBeDeleted = n;
n = n->next;
delete toBeDeleted;
count--;
}
}
/**Returns the first obj*/
template <typename T>
inline T LinkedList<T>::getFirst()
{
return first->value;
};
/**Returns the last obj*/
template <typename T>
inline T LinkedList<T>::getLast()
{
return last->value;
};
I am sorry for alot of code here. And I hope its not a obvious failer.
Edit:
Sinus is declared liket his:
class Sinus : public Animation
{
private:
RGB color;
CubeLib* cube;
byte colorcounter;
float time;
public:
Sinus(CubeLib* c) : time(0.0), colorcounter(0), cube(c){
color.r = MAX_COLOR;
color.g = MAX_COLOR;
color.b = MAX_COLOR;
};
~Sinus(){};
void update(short delta);
};
void Sinus::update(short delta)
{
//do this 1000 times
time += (((float)delta)/1000.0);
for (int x = 0; x < 5; x++)
{
float value = (2.0*sin((float)(x + 1)*time*12.0)) + 2.0;
for (int y = 0; y < 5; y++)
{
for (int z = 0; z < 5; z++)
{
if (abs(((float)z) - value) < 0.5)
{
//cube.setLED(x, y, z, depth - 30/5*(int)abs(z-value), 0, 0);
cube->setLED(x, y, z, color);
}
else
{
cube->setLED(x, y, z, 0, 0, 0);
}
}
}
}
colorcounter++;
if (colorcounter > 25)
{
color.r = random(MAX_COLOR);
color.g = random(MAX_COLOR);
color.b = random(MAX_COLOR);
colorcounter = 0;
}
}
The error is really really really small and i noticed it just by luck.
I changed the counter of the list to byte to reduce the steps. But if my list is empty it is -1 so this would not work. Thats all! changed the count to short type and it works!
template <typename T>
class LinkedList
{
private:
struct Node
{
Node* prev;
Node* next;
T value;
};
Node* last;
Node* first;
short count; // HERE
/...
};

Infix to Postfix code conversion

I have problem to convert infix to postfix this is my code it takes the characterinfix input but does not show any postfix output Please tell me whats the problem.I have been trying to solve it but i found no problem in it i will be thanks full you if someone find the problem.And the other thing is how may i add {} and [] this brackets too ?
#include <iostream>
#include<string.h>
using namespace std;
template <class T>
class Node
{
public:
T info;
Node *ptrnext;
Node *ptrprevious;
Node()
{
info = 0;
ptrnext = 0;
ptrprevious = 0;
}
Node(T e, Node *n, Node *p)
{
info = e;
ptrnext = n;
ptrprevious = p;
}
};
template <class T>
class DLinkedList
{
private:
Node<T> *head;
Node<T> *tail;
public:
DLinkedList()
{
head = 0;
tail = 0;
}
bool isEmpty();
void addToHead(T e);
void addToTail(T e);
void deleteFromHead();
void deleteFromTail();
void display();
T getHead();
int numofNodes();
~DLinkedList(){
if(!isEmpty())
{
while(head!=0){
if(head==tail)
{
delete head;
head=0;
tail=0;
}
else{
Node<T> *ptrtemp=head;
head=head->ptrnext;
head->ptrprevious=NULL;
delete ptrtemp;
}
}
}
}
};
template <class T>
bool DLinkedList<T>::isEmpty()
{
if (head == 0)
{
return true;
}
else
{
return false;
}
}
template <class T>
void DLinkedList<T>::addToHead(T e)
{
Node<T> *ptrnode = new Node<T>(e,0,0);
if(isEmpty())
{
head = ptrnode;
tail = ptrnode;
}
else
{
ptrnode->ptrnext = head;
head->ptrprevious = ptrnode;
ptrnode->ptrprevious = 0;
head = ptrnode;
}
}
template <class T>
void DLinkedList<T>::addToTail(T e)
{
Node<T> *ptrnode = new Node<T>(e,0,0);
if(isEmpty())
{
head = ptrnode;
tail = ptrnode;
}
else
{
tail->ptrnext = ptrnode;
ptrnode->ptrprevious = tail;
ptrnode->ptrnext = 0;
tail = ptrnode;
}
}
template <class T>
void DLinkedList<T>::deleteFromHead()
{
if(!isEmpty())
{
if(head == tail)
{
delete head;
head = 0;
tail = 0;
}
else
{
Node<T> *ptrtemp = head;
head = head->ptrnext;
head->ptrprevious = 0;
delete ptrtemp;
}
}
}
template <class T>
void DLinkedList<T>::deleteFromTail()
{
if(!isEmpty())
{
if(head == tail)
{
delete tail;
head = 0;
tail = 0;
}
else
{
Node<T> *ptrtemp = tail;
tail = tail->ptrprevious;
tail->ptrnext = 0;
delete ptrtemp;
}
}
}
template <class T>
void DLinkedList<T>::display()
{
if(!isEmpty())
{
Node<T> *ptrtemp = head;
while(ptrtemp->ptrnext != 0)
{
cout<<ptrtemp->info;
ptrtemp = ptrtemp->ptrnext;
}
cout<<ptrtemp->info<<endl;
}
}
template <class T>
T DLinkedList<T>::getHead()
{
if(isEmpty())
{
return 0;
}
else
{
return head->info;
}
}
template <class T>
int DLinkedList<T>::numofNodes()
{
if(isEmpty())
{
return 0;
}
else
{
int count = 0;
Node<T> *ptrtemp = head;
while(ptrtemp->ptrnext != 0)
{
count++;
ptrtemp = ptrtemp->ptrnext;
}
count++;
return count;
}
}
template <class T>
class Stack:public DLinkedList<T>
{
private:
int maxStackSize;
public:
Stack()
{
maxStackSize = 10;
}
bool isEmpty();
bool isFull();
void Push(T e);
T Pop();
void display();
T topvalue();
};
template <class T>
bool Stack<T>::isEmpty()
{
bool r= DLinkedList<T>::isEmpty();
return r;
}
template <class T>
bool Stack<T>::isFull()
{
int totalNodes = DLinkedList<T>::numofNodes();
if(totalNodes == maxStackSize)
{
return true;
}
else
{
return false;
}
}
template <class T>
void Stack<T>::Push(T e)
{
if( isFull() )
{
cout<<"Stack Full "<<endl;
}
else
{
DLinkedList<T>::addToHead(e);
}
}
template <class T>
T Stack<T>::Pop()
{
if(isEmpty())
{
return 0;
}
else
{
T n = DLinkedList<T>::getHead();
DLinkedList<T>::deleteFromHead();
return n;
}
}
template <class T>
void Stack<T>::display()
{
if( isEmpty() )
{
cout<<"Stack Empty!!"<<endl;
}
else
{
DLinkedList<T>::display();
}
}
template<class T>
T Stack<T>::topvalue()
{
T temp;
temp=DLinkedList<T>::getHead();
return temp;
}
int main()
{
Stack<char> obj;
char input[20];
cout<<"Enter Values \n";
cin>>input;
int size= strlen(input);
for(int i=0; i <size ; i++)
{
//======= For + or - Operators=========
if(input[i]=='+' || input[i]=='-')
{
if(obj.topvalue()=='+' || obj.topvalue()=='-')
{ //======= CASE-1=======
cout<<obj.Pop();
obj.Push(input[i]);
}
else if(obj.topvalue()=='*' || obj.topvalue()=='/')
{
//======= CASE-2=========
cout<<obj.Pop();
if(obj.topvalue()=='*' || obj.topvalue()=='/')
{
cout<<obj.Pop();
}
obj.Push(input[i]);
}
else if(obj.topvalue()=='(')
{
//======= CASE-3=========
obj.Push(input[i]);
}
else if(obj.isEmpty())
{
//======= CASE-4=========
obj.Push(input[i]);
}
}
// ++++++++++ FOR * and / Operators ++++++++
else if(obj.topvalue()=='*' || obj.topvalue()=='/')
{
if(obj.topvalue()=='+' || obj.topvalue()=='-')
{
//======= CASE-1=========
cout<<obj.Pop();
obj.Push(input[i]);
}
else if(obj.isEmpty())
{
//======= CASE-2=========
obj.Push(input[i]);
}
else if(obj.topvalue()=='(')
{
//======= CASE-3=========
obj.Push(input[i]);
}
else
{
//======= CASE-4=========
obj.Push(input[i]);
}
}
// ++++++++++ Opening bracket ++++++++
else if (obj.topvalue()=='(')
{
obj.Push(input[i]);
}
// ++++++++++ Closing Bracket ++++++++
else if(input[i] != ')')
{
while(obj.topvalue() != '(')
{
cout<<obj.Pop();
}
obj.Pop();
}
// ++++++++++ Operands ++++++++
else
{
cout<<input[i];
}
}
// ++++++++++ Print All values from the Stack and empty it++++++++
while(!obj.isEmpty())
{
cout<<obj.Pop();
}
return 0;
}
>
You have made mistake in following line:
else if (input[i] != ')')
due to which the program is going into infinite loop.
It needs to be:
else if (input[i] == ')')

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.