I'm building a Red-Black Tree, but may be there are some problems with my class RBTree's destructor. I add 10^7 value to the tree, and then call the destructor, but the memory seem to be not freed up. (I look at the System Monitor and my program still use 200MB).
Could you tell me what is wrong with my destructor. This is my source code.
Sorry for my poor English.
#include<cstdio>
#include<cstdlib>
#include<iostream>
using namespace std;
enum Color {RED, BLACK};
template<class Data> class RBNode;
template<class Data> class RBTree;
template<class Data> class RBNode {
Color color; RBNode *p, *left, *right;
public:
Data v;
RBNode(Color color, RBNode *p, RBNode *left, RBNode *right, Data v):
color(color), p(p), left(left), right(right), v(v) {}
RBNode() {}
friend class RBTree<Data>;
};
template<class Data> class RBTree {
typedef RBNode<Data> Node;
typedef Node * PNode;
PNode root, nil;
void LeftRotate(PNode x) {
PNode y = x->right; x->right = y->left;
if(y->left != nil) y->left->p = x;
y->p = x->p;
if(x->p == nil) root = y;
else if(x == x->p->left) x->p->left = y;
else x->p->right = y;
y->left = x; x->p = y;
}
void RightRotate(PNode y) {
PNode x = y->left; y->left = x->right;
if(x->right != nil) x->right->p = y;
x->p = y->p;
if(y->p == nil) root = x;
else if(y == y->p->left) y->p->left = x;
else y->p->right = x;
x->right = y; y->p = x;
}
void insertFixUp(PNode z) {
while(z->p->color == RED) {
if(z->p == z->p->p->left) {
PNode y = z->p->p->right;
if(y->color == RED) z->p->color = y->color = BLACK, z->p->p->color = RED, z = z->p->p;
else {
if(z == z->p->right) LeftRotate(z = z->p);
z->p->color = BLACK; z->p->p->color = RED; RightRotate(z->p->p);
}
} else {
PNode y = z->p->p->left;
if(y->color == RED) z->p->color = y->color = BLACK, z->p->p->color = RED, z = z->p->p;
else {
if(z == z->p->left) RightRotate(z = z->p);
z->p->color = BLACK; z->p->p->color = RED; LeftRotate(z->p->p);
}
}
}
root->color = BLACK;
}
public:
RBTree() {
nil = new Node;
nil->color = BLACK;
nil->p = nil->left = nil->right = nil;
nil->v = Data();
root = nil;
}
~RBTree() {
delete root;
delete nil;
}
void insert(Data v) {
PNode y = nil, x = root;
while(x != nil) {
y = x;
x = v < x->v ? x->left : x->right;
}
PNode z = new Node; *z = Node(RED, y, nil, nil, v);
if(y == nil) root = z;
else if(v < y->v) y->left = z;
else y->right = z;
insertFixUp(z);
}
};
int main() {
RBTree<int> tree;
for(int i = 0; i < 10000000; ++i) tree.insert(i);
tree.~RBTree();
getchar();
return 0;
}
You need to add a destructor to your RBNode, which deletes its children:
template<class Data> class RBNode {
...
~RBNode() {
delete left;
delete right;
}
...
};
As is, you will delete the root node when the tree is deleted, but the root node itself doesn't free its resources. Because of this, you lose all references to the child nodes of root, and all their child nodes, etc. Because you no longer have a reference to these nodes, you can't delete them, you have a memory leak.
The destructor ensures that when we're about to lose our references to a node's children, these children get freed (and their children and so on).
First, what's wrong with it is that you did not use a smart pointer. Secondly, you did not use a smart pointer in your Node classes, so when the root is deleted, none of the other objects are deleted.
Your tree nodes don't appear to recursively delete their children. You need a destructor in the node and then everything will cascade when the root gets destroyed.
Your destructor only frees up two elements: root and nil. To free up the rest of the tree, you should somehow propagate freeing up the elements down the tree, like:
~RBNode() {
if (left != nil ) delete left;
if (right != nil) delete right;
}
(this is just the idea, of course this code won't literally work because you don't see nil in the destructor).
I found my destructor, but i had some more attributes, like size and the parent pointer, but i think it will help
~RBTree() {
RBNode *p(root);
while(size!=0) {
if(p==root && size==1) { delete root; size--;}
else if(p->right!=0) p=p->right;
else if(p->left!=0) p=p->left;
else {
RBNode *c(p);
p=p->parent;
if(p->left==c) {
delete c;
p->left=0;
}
else {
delete c;
p->right=0;
}
size--;
}
}
}
Related
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);
}
Segmentation faults when trying to delete a node with 2 children
So i've recently started studying algorithms and have been working a bit on binary search trees, basing my C++ code on the pseudo code taken from the book Introduction to Algorithms. I'm however having large issues with it's delete function for it's binary search tree. The code for the delete function is:
void bstDelete(BSTtree &bst, int key)
{
treeNode *z = findNode(bst, key);
if (z != nullptr)
{
treeNode *y = z;
treeNode *x;
if (z->left == bst.NIL)
{
x = z->right;
transplant(bst, z, z->right);
}
else if (z->right == bst.NIL)
{
x = z->left;
transplant(bst, z, z->left);
}
else
{
y = treeMin(z->right);
x = y->right;
if (y->parent == z)
{
x->parent = y;
}
else
{
transplant(bst, y, y->right);
y->right = z->right;
y->right->parent = y;
}
transplant(bst, z, y);
y->left = z->left;
y->left->parent = y;
}
}
}
Transplant function:
void transplant(BSTtree &bst, treeNode *u, treeNode *v)
{
if (u->parent == bst.NIL)
{
v->right = u->right;
v->left = u->left;
v->right->parent = v;
v->left->parent = v;
bst.root = v;
}
else if (u == u->parent->left)
{
u->parent->left = v;
}
else
{
u->parent->right = v;
}
v->parent = u->parent;
}
I'm not expecting someone to debug my code, I've just sat pretty much for multiple days trying to figure it out, looking at other people's versions of the delete function trying to understand why mine doesn't work. There's also the issue of why the book's own delete function doesn't do it's job, or if it's just me who's at fault. I would really appreciate if someone could take a look at this. I've been looking around quite a lot and still haven't found anyone having issues with this.
Edit
Added other parts related to the code
treeNode *findNode(RBtree bst, int key)
{
treeNode *z = nullptr;
treeNode *x = bst.root;
treeNode *y = bst.NIL;
while (x != nullptr && x != bst.NIL)
{
y = x;
if (key < x->value)
{
x = x->left;
}
else
{
x = x->right;
}
if (y->value == key)
{
break;
}
}
if (y->value == key)
{
z = y;
}
return z;
}
treeNode *treeMin(treeNode *root)
{
treeNode *treeNode = root;
while (treeNode->left != nullptr)
{
treeNode = treeNode->left;
}
return treeNode;
}
struct treeNode
{
treeNode *left;
treeNode *right;
treeNode *parent;
std::string color;
int value;
treeNode() : left(nullptr), right(nullptr), parent(nullptr) {}
treeNode(int paramValue) : left(nullptr), right(nullptr), parent(nullptr), value(paramValue) {}
treeNode(int paramValue, treeNode *parent) : value(paramValue), parent(parent) {}
};
struct BSTtree
{
treeNode *root;
treeNode *NIL;
BSTtree()
{
NIL = new treeNode();
root = nullptr;
}
};
Reason i have with NIL is so that i can easier make this into an RB tree later on. The smallest scale needed to cause a crash is a 3 node tree, where you have a root, and it has a right and left child. That way you push the delete function into case three, where it has to find a successor and transplant it. It's in this part of the delete-function which it crashes and gives me a segmentation-fault.
Edit 2
Code which causes a crash:
int main()
{
BSTtree bst;
bstInsert(bst, 5);
bstInsert(bst, 7);
bstInsert(bst, 2);
bstDelete(bst, 5);
}
Insert function
void bstInsert(BSTtree &bst, int key)
{
treeNode *z = new treeNode(key);
treeNode *y = bst.NIL;
treeNode *x = bst.root;
while (x != nullptr && x != bst.NIL)
{
y = x;
if (z->value < x->value)
{
x = x->left;
}
else
{
x = x->right;
}
}
z->parent = y;
if (y == bst.NIL)
{
bst.root = z;
z->parent = bst.NIL;
}
else if (z->value < y->value)
{
y->left = z;
}
else
{
y->right = z;
}
z->left = bst.NIL;
z->right = bst.NIL;
}
The nullptr is not a problem here as it's resolved in the insert function, as you can see if it's root, root is given bst.NIL as it's parent. I agree it's error prone to have this construction, it's only there to be able to be used for red and black trees which uses a specific NIL node instead of nullptr.
I've resolved the issues, firstly the treeMin() function is faulty. It should take in an additional parameter which is BSTtree bst and instead of while (treeNode->left != nullptr) it should be while (treeNode->left != bst.NIL), outside of this one of the constructors in treeNode is faulty, this one being treeNode(int paramValue, treeNode *parent) : value(paramValue), parent(parent) {}, it should instead be changed into:
treeNode(int paramValue, treeNode *paramParent) {
value = paramValue;
parent = paramParent;
}
I have been staring at this all day and have gotten slightly somewhere, but it's still not working correctly! Just trying to 'put' (really insert, or find if it's there) an element k into a LL red black tree. Here's my method:
Node * RPut(Node* p, const K& k, Node*& location)
{
// if you are at the bottom of the tree,
// add new node at bottom of the tree
if (p == 0)
{
// new red note with new data
location = NewNode(k, Data(), RED);
return location;
}
if(greater_(k,p->key_))
{
// if it's greater than the root, move down to the left child
p->left_ = Rput(p->left_, k, location);
}
// right subtree
else if (greater_(p->key_,k))
{
// but if the key is less than root, move down to right child
p->right_ = Rput(p->right_, k, location);
}
// if they are equal
else
{
location = p;
}
// code for rotating
// this sort of worked.
if(p->right_ && p->right_->IsRed())
{
p = RotateLeft(p);
if (p->left_->IsBlack())
{
p->SetBlack();
p->left_->SetRed();
}
}
if (p->left_ && p->left_->IsRed())
{ if (p->left_->left_ && p->left_->left_->IsRed())
{
p = RotateRight(p);
p->left_->SetBlack();
p->right_->SetBlack();
}
}
return p;
}
I know my rotate methods work perfectly. This inserts correctly until the fifth element (I haven't tried every combination, but usually.) For instance, abcde inserted correctly would be
d
b e
a c --
[with b as red node]
mine works but stops here, giving me:
b
a d
- - c e
with NO red nodes.
Anyone see anything obvious I am overlooking or why it isn't working properly? Any help at all much appreciated.
Thanks!
This does not directly answer the question, but have you read Sedgewick's paper on left-leaning red black trees? The code in it is exceptionally clear, there are beautiful diagrams explaining how things work, and, I imagine, it would be straight-forward to reimplement everything into C++.
Edit
I tried, for fun to implement Sedgewick's code. It turns out the paper had a few methods/subroutines left out that would have been pretty helpful to include. Anyway, my C++11 implementation, along with some tests, follows.
Since Java does automagic memory management, Sedgewick doesn't explicitly note where memory should be freed in his code. Rather than try to figure this out for a quick project and possibly leave memory leaks, I've opted to use std::shared_ptr, which provides a similar worry-free behaviour.
#include <iostream>
#include <vector>
#include <cstdlib>
#include <memory>
template<class keyt, class valuet>
class LLRB {
private:
static const bool COLOR_RED = true;
static const bool COLOR_BLACK = false;
class Node {
public:
keyt key;
valuet val;
std::shared_ptr<Node> right;
std::shared_ptr<Node> left;
bool color;
Node(keyt key, valuet val){
this->key = key;
this->val = val;
this->color = COLOR_RED;
this->right = nullptr;
this->left = nullptr;
}
};
typedef std::shared_ptr<Node> nptr;
nptr root;
nptr rotateLeft(nptr h){
nptr x = h->right;
h->right = x->left;
x->left = h;
x->color = h->color;
h->color = COLOR_RED;
return x;
}
nptr rotateRight(nptr h){
nptr x = h->left;
h->left = x->right;
x->right = h;
x->color = h->color;
h->color = COLOR_RED;
return x;
}
nptr moveRedLeft(nptr h){
flipColors(h);
if(isRed(h->right->left)){
h->right = rotateRight(h->right);
h = rotateLeft(h);
flipColors(h);
}
return h;
}
nptr moveRedRight(nptr h){
flipColors(h);
if(isRed(h->left->left)){
h = rotateRight(h);
flipColors(h);
}
return h;
}
void flipColors(nptr h){
h->color = !h->color;
h->left->color = !h->left->color;
h->right->color = !h->right->color;
}
bool isRed(const nptr h) const {
if(h==nullptr) return false;
return h->color == COLOR_RED;
}
nptr fixUp(nptr h){
if(isRed(h->right) && !isRed(h->left)) h = rotateLeft (h);
if(isRed(h->left) && isRed(h->left->left)) h = rotateRight(h);
if(isRed(h->left) && isRed(h->right)) flipColors (h);
return h;
}
nptr insert(nptr h, keyt key, valuet val){
if(h==nullptr)
return std::make_shared<Node>(key,val);
if (key == h->key) h->val = val;
else if(key < h->key) h->left = insert(h->left, key,val);
else h->right = insert(h->right,key,val);
h = fixUp(h);
return h;
}
//This routine probably likes memory
nptr deleteMin(nptr h){
if(h->left==nullptr) return nullptr;
if(!isRed(h->left) && !isRed(h->left->left))
h = moveRedLeft(h);
h->left = deleteMin(h->left);
return fixUp(h);
}
nptr minNode(nptr h){
return (h->left == nullptr) ? h : minNode(h->left);
}
//This routine leaks memory like no other!! I've added a few cleanups
nptr remove(nptr h, keyt key){
if(key<h->key){
if(!isRed(h->left) && !isRed(h->left->left))
h = moveRedLeft(h);
h->left = remove(h->left, key);
} else {
if(isRed(h->left))
h = rotateRight(h);
if(key==h->key && h->right==nullptr)
return nullptr;
if(!isRed(h->right) && !isRed(h->right->left))
h = moveRedRight(h);
if(key==h->key){
std::shared_ptr<Node> mn = minNode(h->right);
h->val = mn->val;
h->key = mn->key;
h->right = deleteMin(h->right);
} else {
h->right = remove(h->right, key);
}
}
return fixUp(h);
}
void traverse(const nptr h) const {
if(h==nullptr)
return;
traverse(h->left);
std::cout<< h->key << "=" << h->val <<std::endl;
traverse(h->right);
}
public:
LLRB(){
root = nullptr;
}
void traverse() const {
traverse(root);
}
valuet search(keyt key){
nptr x = root;
while(x!=nullptr){
if (key == x->key) return x->val;
else if (key < x->key) x=x->left;
else x=x->right;
}
return keyt();
}
void insert(keyt key, valuet val){
root = insert(root,key,val);
root->color = COLOR_BLACK;
}
void remove(keyt key){
root = remove(root,key);
root->color = COLOR_BLACK;
}
};
int main(){
for(int test=0;test<500;test++){
LLRB<int,int> llrb;
std::vector<int> keys;
std::vector<int> vals;
for(int i=0;i<1000;i++){
//Ensure each key is unique
int newkey = rand();
while(llrb.search(newkey)!=int())
newkey = rand();
keys.push_back(newkey);
vals.push_back(rand()+1);
llrb.insert(keys.back(),vals.back());
}
//llrb.traverse();
for(int i=0;i<1000;i++){
if(llrb.search(keys[i])!=vals[i]){
return -1;
}
}
for(int i=0;i<500;i++)
llrb.remove(keys[i]);
for(int i=500;i<1000;i++){
if(llrb.search(keys[i])!=vals[i]){
return -1;
}
}
}
std::cout<<"Good"<<std::endl;
}
I am working on a project in C++ in which I have to create a binary search tree that inserts items from an array. I have to use the following insert algorithm:
tree-insert(T, z)
y = NIL
x = T.root
while x != NIL
y = x
if z.key < x.key
x = x.left
else x = x.right
z.p = y
if y == NIL
T.root = z
else if z.key < y.key
y.left = z
else y.right = z
Here is what I have so far:
#include <iostream>
using namespace std;
struct node
{
int key;
node* left;
node* right;
node* p;
node* root;
};
void insert(node*, node*);
void printinorder(node*);
int main()
{
node *root;
node* tree = new node;
node* z = new node;
int array [10] = {30, 10, 45, 38, 20, 50, 25, 33, 8, 12};
for (int i = 0; i < 10; i++)
{
z->key = array[i];
insert(tree, z);
}
printinorder(tree);
return 0;
}
void insert(node *T, node *z)
{
node *y = nullptr;
node* x = new node;
x = T->root;
while (x != NULL)
{
y = x;
if (z->key < x->key)
x = x->left;
else
x = x->right;
}
z->p = y;
if (y == NULL)
T->root = z;
else if (z->key < y->key)
y->left = z;
else
y->right = z;
}
void printinorder(node *x)
{
if (x != NULL)
{
printinorder(x->left);
cout << x->key << endl;
printinorder(x->right);
}
}
This code compiles however when I run it, it seg faults. I believe the problem has something to do with the nodes I am creating or my function calls.
Thanks for your help.
Besides the issues noted in the comments, the biggest bug in this code is a lack of a constructor that initializes all pointers in a new node to NULL.
As such, every node you create will have its pointers containing random garbage. You code initializes some of them, but most are not. Trying to use uninitialized pointers will result in an immediate crash.
You need to fix all the problems that have been noted in the comments, and have a proper constructor for your node class.
I'm coding the Red-Black-Tree by following Introduction to Algorithms. And when it comes to the right-rotate function, one of my pointer was modified unexpectedly.
void RBTree::RightRotate(pNode &z)
{
pNode l=z->lChild;
z->lChild = l->rChild; //link z->l-r to z as a lChild
if(l->rChild != nil)
l->rChild->p = z;
l->p = z->p; //when pass the tree's root as parameter
//z,after executing this line, z was
//modified to pointing to nil
//(known from debug window), why?
if(z->p == nil)
root = l;
else if (z == z->p->lChild)
z->p->lChild = l;
else
z->p->rChild = l;
l->rChild=z;
z->p=l;
}
And just as Introduction to Algorithms goes, I set nil pointer in my class.
Since only when root was passed as parameter z can cause this problem, I defer it's something wrong with nil and root.The following is the whole code.
:
#include
#include
#include
#define RED 1
#define BLACK 0
using namespace std;
typedef struct Node
{
int color, val;
struct Node* lChild, *rChild, *p;
Node(int val_, struct Node* tmp)
{color=RED, val=val_,lChild=rChild=p=tmp;}
Node(){color=BLACK, val=0,lChild=rChild=p=NULL;}
}Node,*pNode;
class RBTree
{
public:
RBTree()
{
root=NULL;
}
~RBTree()
{
Free_(root);
}
void Free_(pNode p)
{
if(p!=NULL)
{
Free_(p->lChild);
Free_(p->rChild);
delete(p);
p=NULL;
}
}
pNode FindMin() const
{
pNode p=root;
if (p)
while(p->lChild)
p=p->lChild;
return p;
}
pNode FindMax() const
{
pNode p=root;
if (p)
while(p->rChild)
p=p->rChild;
return p;
}
void Print(pNode p, int n) const
{
if(!p)
return;
Print(p->rChild,n+2);
for(int i=0;ivalcolor==1)?"R":"B")lChild,n+2);
}
pNode Root() {return root;}
void Insert(int const& val_);
void InsertFixup(pNode &z);
void LeftRotate(pNode &p);
void RightRotate(pNode &p);
pNode Search(pNode const &p, int x) const;
void Delete(pNode &p, int x);
private:
pNode root;
static pNode nil;
};
pNode RBTree::nil = new Node();
/*
Inserting pipiline:
Insert node into RBTree, then fixup.
In the fixup procedure , rotate may be called
*/
void RBTree::InsertFixup(pNode &z)
{
while (z->p->color == RED)
{
pNode y;
if (z->p == z->p->p->lChild)
{
y=z->p->p->rChild;
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->rChild)
{
z = z->p;
LeftRotate(z);
}
z->p->color = BLACK;
z->p->p->color = RED;
RightRotate(z->p->p);
}
}
else
{
y=z->p->p->lChild;
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->lChild)
{
z = z->p;
RightRotate(z);
}
z->p->color = BLACK;
z->p->p->color = RED;
LeftRotate(z->p->p);
}
}
}
root->color = BLACK;
}
void RBTree::Insert(int const &val_)
{
pNode z=new Node(val_, nil); //set val, lChild, rChild, p to NULL, color to RED
pNode x = root;
pNode pre = nil;
if(NULL == root)
root = z;
else
{
while (x!=nil)
{
pre=x;
x=(x->valrChild:x->lChild;
}
z->p = pre;
if (z->val val)
pre->lChild = z;
else
pre->rChild = z;
}
InsertFixup(z);
}
//left-rotate
//denote z, z's rChild == r
//parent changed: z, r, r's lChild
//child chagend: z->rChild, r->lChild, z->p->lChild/rChild
void RBTree::LeftRotate(pNode &z)
{
pNode r=z->rChild;
z->rChild = r->lChild; //link p->r-l to p as a r
if(r->lChild != nil)
r->lChild->p = z;
r->p = z->p;
if(z->p == nil)
root = r;
else if (z == z->p->lChild)
z->p->lChild = r;
else
z->p->rChild = r;
r->lChild=z;
z->p=r;
}
// right-rotate
void RBTree::RightRotate(pNode &z)
{
pNode l=z->lChild;
z->lChild = l->rChild; //link p->l-r to p as a l
if(l->rChild != nil)
l->rChild->p = z;
l->p = z->p;
if(z->p == nil) //link parent from top to bottom
root = l;
else if (z == z->p->lChild)
z->p->lChild = l;
else
z->p->rChild = l;
l->rChild=z;
z->p=l;
}
int main()
{
int a[9] = {11, 2, 14, 1, 7, 15, 5, 8, 4};
RBTree tr;
for(int i=0;i
Am I using nil in a wrong way?
Thanks.
Nill is not a C++ expression. However some environments might include it, just using it as an alias for NULL or 0. If you use C++11, I would recommend nullptr
Try to have a look whether
l->p < z && z< l->p + sizeof(z)
If that is the case, you are assigning to z.