So I wrote a Ranked self-balancing Binary Search Tree instead of using std::set. I was expecting it to work faster for getting rank of elements, but it seems to take more time than using std::set and iterating through to find rank. Is there any way to speed it up?
#include<bits/stdc++.h>
struct treeNode{
int data;
int leftsize; //for finding rank
int height; //for balancing during insertions and deletions
treeNode* left;
treeNode* right;
treeNode()
:data(NAN), leftsize(0), left(nullptr), right(nullptr){}
treeNode(int val, int lsize, int ht)
:data(val), leftsize(lsize), height(ht), left(nullptr), right(nullptr){}
};
int height(treeNode* node)
{
if(node == nullptr)
return 0;
return node->height;
}
int getBalance(treeNode* node)
{
if(node==nullptr)
return 0;
return height(node->left) - height(node->right);
}
int parseLeftSub(treeNode* node)
{
if(node == nullptr)
return 0;
int cnt = 1;
cnt += parseLeftSub(node->left);
cnt += parseLeftSub(node->right);
return cnt;
}
void printNode(treeNode* node)
{
if(node == nullptr)
return;
printNode(node->left);
std::cout << node->data << " " << node->leftsize << std::endl;
printNode(node->right);
}
treeNode* createNode(int val)
{
treeNode* node = new treeNode(val, 1, 1);
return node;
}
treeNode* createTree(std::vector<int>& a, int start, int end)
{
if(start>end)
return nullptr;
int mid = (start + end)/2;
treeNode* node = createNode(a[mid]);
node->left = createTree(a, start, mid-1);
node->right = createTree(a, mid+1, end);
node->leftsize += parseLeftSub(node->left);
return node;
}
treeNode* rightRotate(treeNode* y)
{
treeNode* x = y->left;
treeNode* T2 = x->right;
// Perform rotation
x->right = y;
y->left = T2;
// Update heights
y->height = std::max(height(y->left),
height(y->right)) + 1;
x->height = std::max(height(x->left),
height(x->right)) + 1;
// Return new root
y->leftsize = parseLeftSub(y->left) + 1;
return x;
}
treeNode* leftRotate(treeNode* x)
{
treeNode* y = x->right;
treeNode* T2 = y->left;
// Perform rotation
y->left = x;
x->right = T2;
// Update heights
x->height = std::max(height(x->left),
height(x->right)) + 1;
y->height = std::max(height(y->left),
height(y->right)) + 1;
// Return new root
y->leftsize = parseLeftSub(y->left) + 1;
return y;
}
treeNode* insertNode(int val, treeNode* node)
{
if(node == nullptr)
return createNode(val);
if(val < node->data)
node->left = insertNode(val, node->left);
else if(val > node->data)
node->right = insertNode(val, node->right);
else
return node;
node->height = 1 + std::max(height(node->left), height(node->right));
node->leftsize = parseLeftSub(node->left) + 1;
int balance = getBalance(node);
if(balance > 1 && val < node->left->data)
return rightRotate(node);
else if(balance < -1 && val > node->right->data)
return leftRotate(node);
else if(balance > 1 && val > node->left->data)
{
node->left = leftRotate(node->left);
return rightRotate(node);
}
else if(balance < -1 && val < node->right->data)
{
node->right = rightRotate(node->right);
return leftRotate(node);
}
return node;
}
treeNode* searchNode(int val, treeNode* node)
{
if(node == nullptr)
return nullptr;
treeNode* foundNode = nullptr;
if(val == node->data)
return node;
else if(val < node->data)
foundNode = searchNode(val, node->left);
else
foundNode = searchNode(val, node->right);
return foundNode;
}
treeNode* findLowerBound(int val, treeNode* node)
{
if(node == nullptr)
return nullptr;
if(val == node->data)
return node;
else if(val>node->data)
{
return(findLowerBound(val, node->right));
}
treeNode* temp = findLowerBound(val, node->left);
if(temp != nullptr && temp->data >= val)
return temp;
else
return node;
}
treeNode* findUpperBound(int val, treeNode* node)
{
if(node == nullptr)
return nullptr;
if(val == node->data)
return node;
else if(val<node->data)
{
return(findUpperBound(val, node->left));
}
treeNode* temp = findUpperBound(val, node->right);
if(temp != nullptr && temp->data <= val)
return temp;
else
return node;
}
treeNode* findMinNode(treeNode* node)
{
if(node->left == nullptr)
return node;
return (findMinNode(node->left));
}
treeNode* deleteNode(int val, treeNode*& node)
{
if(node == nullptr)
return nullptr;
if(node->data > val)
node->left = deleteNode(val, node->left);
else if(node->data < val)
node->right = deleteNode(val, node->right);
else
{
if(node->left==nullptr && node->right==nullptr)
{
delete node;
node = nullptr;
}
else if(node->left==nullptr)
{
treeNode* temp = node;
node = node->right;
delete temp;
}
else if(node->right==nullptr)
{
treeNode* temp = node;
node = node->left;
delete temp;
}
else
{
treeNode* temp = findMinNode(node->right);
node->data = temp->data;
node->right = deleteNode(temp->data, node->right);
}
}
if (node == NULL)
return node;
node->leftsize = parseLeftSub(node->left) + 1;
node->height = 1 + std::max(height(node->left),
height(node->right));
int balance = getBalance(node);
if (balance > 1 &&
getBalance(node->left) >= 0)
return rightRotate(node);
if (balance > 1 &&
getBalance(node->left) < 0)
{
node->left = leftRotate(node->left);
return rightRotate(node);
}
if (balance < -1 &&
getBalance(node->right) <= 0)
return leftRotate(node);
if (balance < -1 &&
getBalance(node->right) > 0)
{
node->right = rightRotate(node->right);
return leftRotate(node);
}
return node;
}
int findRank(int val, treeNode* node)
{
int rank = node->leftsize;
if(node==nullptr)
{
return -1;
}
if(val<node->data)
{
rank -= node->leftsize;
rank += findRank(val, node->left);
}
else if(val>node->data)
{
rank += findRank(val, node->right);
}
return rank;
}
I know its quite a lot. Also can any other stl containers be used to find rank, insert and delete efficiently
Related
I was implementing binary search tree and also inputting values in to the tree and traversing using inorder traversal. Every function of my class works except deletion, deletion does work at all. Moreover, I would appreciate if someone explains to me why we return values for deletion?
#include <iostream>
using namespace std;
class node {
public:
int key;
node* right;
node* left;
node(int val)
{
key = val;
right = NULL;
left = NULL;
}
};
class BinarySearchTree{
public:
node* root = NULL;
node* insert(node* root, int val) {
if (root == NULL) {
return new node(val);}
else if (val > root->key) {
root->right = insert(root->right, val);
}
else if (val < root->key) {
root->left = insert(root->left, val);
}
return root;}
void inorder(node* root) {
if (root == NULL)
return;
inorder(root->left);
cout << "our node is that " << root->key << endl;
inorder(root->right);
}
int minimumm(node* root) {
node* current = root;
while (current->left != NULL) {
current = current->left;
}
return (current->key);
}
node* deletenode(node* root, int val) {
if (root == NULL) {
return root;
}
else if (val > root->key) {
deletenode(root->right, val);
}
else if (val < root->key) {
deletenode(root->left, val);}
else {
if (root->right == NULL && root->left == NULL) {
delete(root);
return NULL;
}
else if (root->right == NULL) {
node* temp = root->left;
delete(root);
return temp;
}
else if (root->left == NULL) {
node* temp = root->right;
delete(root);
return temp;
}
else {
int temp = minimumm(root->right);
deletenode(root->right, temp);
return root;
}
}
}
};
int main() {
BinarySearchTree bst;
bst.root = bst.insert(bst.root, 100);
bst.root = bst.insert(bst.root, 19);
bst.root = bst.insert(bst.root, 47);
bst.root = bst.insert(bst.root, 3);
bst.root = bst.insert(bst.root, 111);
bst.root = bst.insert(bst.root, 78);
bst.inorder(bst.root);
bst.root = bst.deletenode(bst.root, 78);
bst.root = bst.deletenode(bst.root, 71);
bst.inorder(bst.root);
}
I tried to delete 78 and 71 using deletion class but it didn't work at all
I'm writing a Splay Tree implementation. Code compiles just fine in VS, but the testing system fails with DEADLYSIGNAL.
The specific input for testing is:
search 66
min
max
set 1 20
print
Here is the full code:
#include <iostream>
#include <sstream>
#include <stack>
#include <queue>
#include <cmath>
struct Node
{
int64_t key;
std::string value;
Node* left, * right, * parent;
Node(const int64_t& k) : key(k), left(nullptr), right(nullptr), parent(nullptr) {}
Node(const int64_t& k, const std::string& v, Node* p) : key(k), value(v),
left(nullptr), right(nullptr), parent(p) {}
};
class SplayTree
{
Node* root;
size_t size;
bool isRight(Node* node)
{
if (node && node->parent)
if (node->parent->right == node)
return true;
else
return false;
}
std::pair<int, Node*> Find(const int64_t& key)
{
Node* node = root;
while (node)
{
if (node->key == key)
return { 2, node };
else if (node->key > key)
if (node->left)
node = node->left;
else
return { 0, node };
else if (node->key < key)
if (node->right)
node = node->right;
else
return { 1, node };
}
}
void Merge(Node* left, Node* right)
{
if (!left && !right)
root = nullptr;
else if (!left)
{
root = right;
right->parent = nullptr;
}
else if (!right)
{
root = left;
left->parent = nullptr;
}
else
{
left = Max(left);
left->parent = nullptr;
left->right = right;
right->parent = left;
}
}
void rotateL(Node* node)
{
Node* p = node->parent;
Node* r = node->right;
if (p != nullptr)
if (p->left == node)
p->left = r;
else
p->right = r;
Node* temp = r->left;
r->left = node;
node->right = temp;
node->parent = r;
r->parent = p;
if (temp != nullptr)
temp->parent = node;
}
void rotateR(Node* node)
{
Node* p = node->parent;
Node* l = node->left;
if (p != nullptr)
if (p->left == node)
p->left = l;
else
p->right = l;
Node* temp = l->right;
l->right = node;
node->left = temp;
node->parent = l;
l->parent = p;
if (temp != nullptr)
temp->parent = node;
}
void Zig(Node* node)
{
!isRight(node) ?
rotateR(node->parent) : rotateL(node->parent);
}
void ZigZig(Node* node, bool side)
{
if (side)
{
rotateL(node->parent->parent);
rotateL(node->parent);
}
else
{
rotateR(node->parent->parent);
rotateR(node->parent);
}
}
void ZigZag(Node* node, bool side)
{
if (side)
{
rotateL(node->parent);
rotateR(node->parent);
}
else
{
rotateR(node->parent);
rotateL(node->parent);
}
}
void Splay(Node* node)
{
while (node->parent != nullptr)
{
if (node->parent == root)
Zig(node);
else if (!isRight(node) && !isRight(node->parent))
ZigZig(node, 0);
else if (isRight(node) && isRight(node->parent))
ZigZig(node, 1);
else if (!isRight(node) && isRight(node->parent))
ZigZag(node, 0);
else
ZigZag(node, 1);
}
root = node;
}
std::string printNode(Node* node)
{
std::string result;
result += '[' + std::to_string(node->key) + ' ' + node->value;
if (node->parent)
result += ' ' + std::to_string(node->parent->key);
result += ']';
return result;
}
Node* Max(Node* node)
{
Node* temp = node;
if (temp)
{
while (temp->right)
temp = temp->right;
Splay(temp);
return temp;
}
else
return nullptr;
}
Node* Min(Node* node)
{
Node* temp = node;
if (temp)
{
while (temp->left)
temp = temp->left;
Splay(temp);
return temp;
}
else
return nullptr;
}
public:
Node* getRoot() { return root; }
SplayTree() : root(nullptr), size(0) { }
SplayTree(uint64_t key)
{
root = new Node(key);
size = 1;
}
~SplayTree()
{
if (root)
{
std::stack<Node*> toDelete;
toDelete.push(root);
while (!toDelete.empty())
{
Node* node = toDelete.top();
if (node->left)
{
toDelete.push(node->left);
node->left = nullptr;
}
else if (node->right)
{
toDelete.push(node->right);
node->right = nullptr;
}
else
{
toDelete.pop();
delete node;
}
}
}
}
bool Add(const int64_t& key, const std::string& value)
{
if (!root)
{
root = new Node(key, value, nullptr);
size++;
return true;
}
else
{
std::pair<int, Node*> result = Find(key);
if (result.first == 2)
return false;
else if (result.first == 0)
{
result.second->left = new Node(key, value, result.second);
Splay(result.second->left);
size++;
return true;
}
else
{
result.second->right = new Node(key, value, result.second);
Splay(result.second->right);
size++;
return true;
}
}
}
std::string Search(const int64_t& key)
{
if (root)
{
std::pair<int, Node*> result = Find(key);
if (result.first == 2)
{
Splay(result.second);
return "1 " + result.second->value;
}
Splay(result.second);
}
return "0";
}
Node* Min() { return Min(root); }
Node* Max() { return Max(root); }
bool Set(const int64_t& key, const std::string& value)
{
std::pair<int, Node*> result = Find(key);
if (result.first == 2)
{
result.second->value = value;
Splay(result.second);
return true;
}
else
return false;
}
bool Delete(const int64_t& key)
{
if (!root)
return false;
std::pair<int, Node*> result = Find(key);
if (result.first == 2)
{
Splay(result.second);
Node* subL = result.second->left;
Node* subR = result.second->right;
Merge(subL, subR);
delete result.second;
size--;
return true;
}
return false;
}
std::string Print()
{
std::string result;
std::queue<Node*> toPrint;
toPrint.push(root);
size_t counter = size;
size_t space = 0;
size_t i = 0;
while (!toPrint.empty())
{
Node* node = toPrint.front();
toPrint.pop();
space++;
if (node)
{
result += printNode(node);
toPrint.push(node->left);
toPrint.push(node->right);
counter--;
}
else
{
result += "_";
toPrint.push(nullptr);
toPrint.push(nullptr);
}
if (space == pow(2, i))
{
result += "\n";
if (counter != 0)
{
i++;
space = 0;
}
}
else
result += " ";
if (counter == 0 && space == pow(2, i))
break;
}
return result;
}
};
int main()
{
std::string data;
std::getline(std::cin, data, '\0');
data += '\n';
std::istringstream is(data);
std::ostringstream os;
SplayTree tree;
int64_t key;
std::string command, value;
bool empty = false;
while (is >> command)
{
if (command.empty())
{
empty = true;
}
if (command == "add" && is.peek() != '\n'
&& is >> key && is.peek() != '\n' && is >> value && is.peek() == '\n')
{
if (!tree.Add(key, value))
os << "error" << std::endl;
}
else if (command == "set" && is.peek() != '\n'
&& is >> key && is.peek() != '\n' && is >> value && is.peek() == '\n')
{
if (!tree.Set(key, value))
os << "error" << std::endl;
}
else if (command == "delete" && is.peek() != '\n'
&& is >> key && is.peek() == '\n')
{
if (!tree.Delete(key))
os << "error" << std::endl;
}
else if (command == "search" && is.peek() != '\n'
&& is >> key && is.peek() == '\n')
{
os << tree.Search(key) << std::endl;
}
else if (command == "min" && is.peek() == '\n')
{
Node* temp = tree.Min();
if (temp)
{
os << temp->key << " "
<< temp->value << std::endl;
}
else
os << "error" << std::endl;
}
else if (command == "max" && is.peek() == '\n')
{
Node* temp = tree.Max();
if (temp)
{
os << temp->key << " "
<< temp->value << std::endl;
}
else
os << "error" << std::endl;
}
else if (command == "print" && is.peek() == '\n')
{
os << tree.Print();
}
else
{
if (!empty)
os << "error" << std::endl;
}
}
std::cout << os.str();
return 0;
}
VS debugger tells me nothing on what causes this error. Sanitazier describes it as read fault, but I can't figure out in which function exactly it happens.
Also, full Sanitizer output:
AddressSanitizer:DEADLYSIGNAL
=================================================================
==26100==ERROR: AddressSanitizer: SEGV on unknown address 0x00000004 (pc 0x08164c7a bp 0xbff0f8d8 sp 0xbff0f420 T0)
==26100==The signal is caused by a READ memory access.
==26100==Hint: address points to the zero page.
Hope someone helps. Thank you in advance.
Since this shows up in search results:
Some part of you code (which you'll find out when you see the full ASan error) is creating an invalid address 0x4 which ASan wants to see the memory of.
It could be say an int accidentally cast to a pointer or an intentional cast like say
auto p = (int*)4;
See full error and the stack trace in it.
Derived class offset calculation in boost::serialization. Is it valid?
I need to make optimized search for vector using binary search tree.
for example I have vector<int> numbers where I store {5,4,3,2,1}
then I copy those 1,2,3,4,5 to binary tree and need to return index where it is stored in vector.
For example, search(4) will have to return 1 because numbers[1] = 4
I've tried giving nodes index but they don't match in the end
Is there a better solution or how do I correctly give index to tree nodes
struct node {
int data;
int index;
node* left;
node* right;
};
node* insert(int x, node* t) {
if(t == NULL) {
t = new node;
t->data = x;
t->index = 0;
t->left = t->right = NULL;
}
else if(x < t->data) {
t->left = insert(x, t->left);
t->index += 1;
}
else if(x > t->data) {
t->right = insert(x, t->right);
t->index += 0;
}
return t;
}
node* find(node* t, int x) {
if(t == NULL)
return NULL;
else if(x < t->data) {
return find(t->left, x);
}
else if(x > t->data) {
return find(t->right, x);
}
else
return t;
}
int main() {
BST t;
vector<int> storage;
for ( int i =0; i< 10; i++) {
storage.push_back(rand()%100 +1);
t.insert(storage[i]);
}
t.display();
t.search(15);
}
node* insert(int x, node* t, int index)
{
if(t == NULL)
{
t = new node;
t->data = x;
t->index = index;
t->left = t->right = NULL;
}
else if(x < t->data)
{
t->left = insert(x, t->left, index);
}
else if(x > t->data)
{
t->right = insert(x, t->right, index);
}
return t;
}
I am trying to insert 0 through 11 into avl and then delete 4, 5, 6 in that order. I am getting sigserv error while deleting 6 in rr_rotation function. This is the first time I am implementing avl and I am new to programming. Where am I going wrong? I added a few comments for my own understanding and to track where the error has occurred. Here is my code:
#include<bits/stdc++.h>
using namespace std;
#define pow2(n) (1 << (n))
struct avl_node {
int data;
//int size;
struct avl_node *left;
struct avl_node *right;
}*root;
class avlTree {
public:
int height(avl_node *);
int diff(avl_node *);
avl_node *rr_rotation(avl_node *);
avl_node *ll_rotation(avl_node *);
avl_node *lr_rotation(avl_node *);
avl_node *rl_rotation(avl_node *);
avl_node* balance(avl_node *);
avl_node* insert(avl_node *, int);
int getBalance(avl_node*);
int getSize(avl_node*);
avl_node* minValueNode(avl_node*);
avl_node* del(avl_node *, int);
void inorder(avl_node *);
void preorder(avl_node *);
int kthsmallest(avl_node*, int);
avlTree() {
root = NULL;
}
};
int avlTree::height(avl_node *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;
}
int avlTree::diff(avl_node *temp) {
int l_height = height(temp->left);
int r_height = height(temp->right);
int b_factor = l_height - r_height;
return b_factor;
}
avl_node *avlTree::rr_rotation(avl_node *parent) {
avl_node *temp;
cout<<"inside rr rotation"<<endl;
cout<<"parent = "<<parent->data<<endl;
temp = parent->right;
if(temp == NULL)
cout<<"yes null 2"<<endl;
//cout<<"parent->right "<<temp->data<<endl;
parent->right = temp->left;
temp->left = parent;
cout<<"temp->left->data "<<temp->left->data<<endl;
return temp;
}
avl_node *avlTree::ll_rotation(avl_node *parent) {
avl_node *temp;
//cout<<"inside ll rotation"<<endl;
//cout<<"parent = "<<parent->data<<endl;
temp = parent->left;
parent->left = temp->right;
temp->right = parent;
return temp;
}
avl_node *avlTree::lr_rotation(avl_node *parent) {
avl_node *temp;
cout<<"inside lr rotation"<<endl;
cout<<"parent = "<<parent->data<<endl;
temp = parent->left;
parent->left = rr_rotation(temp);
return ll_rotation(parent);
}
avl_node *avlTree::rl_rotation(avl_node *parent) {
avl_node *temp;
cout<<"inside rl rotation"<<endl;
cout<<"parent = "<<parent->data<<endl;
temp = parent->right;
parent->right = ll_rotation(temp);
return rr_rotation(parent);
}
avl_node *avlTree::balance(avl_node *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;
}
avl_node *avlTree::insert(avl_node *root, int value) {
//cout<<"Inside insert for val = "<<value<<endl;
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;
}
avl_node* avlTree::minValueNode(avl_node* node) {
avl_node* current = node;
while (current->left != NULL)
current = current->left;
return current;
}
int avlTree::getBalance(avl_node* N) {
if (N == NULL)
return 0;
return height(N->left) - height(N->right);
}
avl_node* avlTree::del(avl_node *root, int value) {
cout<<"del for val = "<<value<<endl;
if (root == NULL){
cout<<"root is null here\n";
return root;
}
// If the key to be deleted is smaller than the
// root's key, then it lies in left subtree
if (value < root->data)
root->left = del(root->left, value);
// If the key to be deleted is greater than the
// root's key, then it lies in right subtree
else if (value > root->data)
root->right = del(root->right, value);
// if key is same as root's key, then This is
// the node to be deleted
else {
// node with only one child or no child
if ((root->left == NULL) || (root->right == NULL)) {
avl_node* temp = root->left ? root->left : root->right;
// No child case
if (temp == NULL) {
temp = root;
root = NULL;
cout<<"Root set to null\n";
}
else{
// One child case
cout<<temp->data<<" copied to root "<<root->data<<"\n";
*root = *temp;
// Copy the contents of
// the non-empty child
}
free(temp);
} else {
// node with two children: Get the inorder
// successor (smallest in the right subtree)
avl_node* temp = minValueNode(root->right);
// Copy the inorder successor's data to this node
root->data = temp->data;
// Delete the inorder successor
root->right = del(root->right, temp->data);
}
} // If the tree had only one node then return
if (root == NULL)
return root;
// STEP 2: UPDATE HEIGHT OF THE CURRENT NODE
//root->height = 1 + max(height(root->left),height(root->right));
// STEP 3: GET THE BALANCE FACTOR OF THIS NODE (to
// check whether this node became unbalanced)
int balance = getBalance(root);
cout<<"balance = "<<balance<<" for root "<<root->data<<endl;
if(root->right == NULL)
cout<<"yes null"<<endl;
// If this node becomes unbalanced, then there are 4 cases// Left Left Case
if (balance > 1 && getBalance(root->left) >= 0){
cout<<"balance1 = "<<getBalance(root->left)<<" for root "<<root->left->data<<endl;
avl_node* t = rr_rotation(root);
//root = rr_rotation(root);
cout<<"Root of the modified sub-tree is "<<t->data<<endl;
return t;
//rr_rotation(root);
}
// Left Right Case
if (balance > 1 && getBalance(root->left) < 0) {
cout<<"balance2 = "<<getBalance(root->left)<<" for root "<<root->left->data<<endl;
cout<<"prev root "<<root->left->data<<endl;
//root->left = ll_rotation(root->left);
root = lr_rotation(root);
cout<<"new root "<<root->data<<endl;
//return rr_rotation(root);
return root;
} // Right Right Case
if (balance < -1 && getBalance(root->right) <= 0){
cout<<"balance3 = "<<getBalance(root->right)<<" for root "<<root->right->data<<endl;
avl_node* t = rr_rotation(root);
cout<<"Root of the modified sub-tree is "<<t->data<<endl;
return t;
//return ll_rotation(root);
}
// Right Left Case
if (balance < -1 && getBalance(root->right) > 0) {
cout<<"balance4 = "<<getBalance(root->right)<<" for root "<<root->right->data<<endl;
//root->right = rr_rotation(root->right);
//return ll_rotation(root);
return rl_rotation(root);
}
return root;
}
void avlTree::inorder(avl_node *tree) {
if (tree == NULL)
return;
inorder(tree->left);
cout << tree->data << " ";
inorder(tree->right);
}
void avlTree::preorder(avl_node *tree) {
if (tree == NULL)
return;
cout << tree->data << " ";
preorder(tree->left);
preorder(tree->right);
}
int avlTree::getSize(avl_node* N){
if(N == NULL)
return 0;
return (getSize(N->left) + 1 + getSize(N->right));
}
int avlTree::kthsmallest(avl_node* N, int k){
int r = getSize(N->left) + 1;
if(k == r)
return N->data;
if(k < r)
return kthsmallest(N->left,k);
if(k > r)
return kthsmallest(N->right,k-r);
return -1;
}
int main(void) {
int n, i, x;
char s;
avlTree tree; for(i=0;i<12;i++){
root = tree.insert(root,i);
tree.preorder(root);
cout<<endl;
}
for(i=4;i<=6;i++){
root = tree.del(root,6);
tree.preorder(root);
cout<<endl;
}
return 0;
}
I was trying to implement AVL Tree in C++, I Implemented key insertion without much problem but while trying to delete a node I ran into use after free bug. I tried to debug with gdb but I was unable to find out the problem, Here's the full code.
#include <iostream>
#include <algorithm>
using namespace std;
class Node;
class AVLTree;
typedef Node* node_ptr;
class Node {
int key;
int height;
node_ptr left;
node_ptr right;
void fix_height() {
int hR, hL = 0;
if (left) hL = left->height;
if (right) hR = right->height;
height = max(hL, hR) + 1;
}
int balance_factor() {
if (left && right)
return left->height - right->height;
if (left && !right)
return left->height;
if (right && !left)
return -right->height;
return 0;
}
public:
Node(int key) :key(key), left(nullptr), right(nullptr),height(1){}
friend class AVLTree;
};
class AVLTree {
node_ptr mRoot;
node_ptr insert(node_ptr node, int key) {
if (!node) return new Node(key);
if (node->key > key) node->left = insert(node->left, key);
else node->right = insert(node->right, key);
return balance(node);
}
node_ptr left_rotate(node_ptr X) {
node_ptr Y = X->right;
X->right = Y->left;
Y->left = X;
X->fix_height();
Y->fix_height();
return Y;
}
node_ptr right_rotate(node_ptr Y) {
node_ptr X = Y->left;
Y->left = X->right;
X->right = Y;
X->fix_height();
Y->fix_height();
return X;
}
node_ptr balance(node_ptr node) {
node->fix_height();
int b_factor = node->balance_factor();
if (b_factor == 2) {
if (node->left->balance_factor() < 0) {
node->left = left_rotate(node->left);
}
return right_rotate(node);
}
else if (b_factor == -2) {
if (node->right->balance_factor() > 0) {
node->right = right_rotate(node->right);
}
return left_rotate(node);
}
return node;
}
node_ptr find_min(node_ptr node) {
if (!node) return nullptr;
if (!node->left) return node;
else return
find_min(node->left);
}
node_ptr remove_min(node_ptr node) {
if (!node->left)
return node->right;
node->left = remove_min(node->left);
return balance(node);
}
node_ptr remove(node_ptr node, int key) {
if (!node) return nullptr;
if (node->key > key)
node->left = remove(node->left, key);
else if (node->key < key)
node->right = remove(node->right, key);
else {
node_ptr L = node->left;
node_ptr R = node->right;
delete node;
if (!R) return L;
node_ptr min = find_min(node->right);
min->right = remove_min(R);
min->left = L;
return balance(min);
}
return balance(node);
}
void print_inorder(node_ptr node) {
if (node) {
print_inorder(node->left);
cout << node->key << " ";
print_inorder(node->right);
}
}
public:
AVLTree() :mRoot(nullptr) {}
void insert(int key) {
mRoot = insert(mRoot, key);
}
void remove(int key) {
mRoot = remove(mRoot, key);
}
void print_inorder() {
cout << endl;
print_inorder(mRoot);
cout << endl;
}
};
int main()
{
AVLTree mtree;
for (int i = 0; i < 3; ++i) {
mtree.insert(i);
}
mtree.remove(0);
mtree.remove(1);
mtree.remove(2);
mtree.print_inorder();
return 0;
}
So, In remove_min(), I am using the same logic as a binary search tree. If sub-tree has a right child, minimum element from that right subtree is returned, and replaced with the target node, If not then just pointer to left subtree is returned and as function returns it balances the disturbed nodes. But somehow deleted node is getting referenced and I am getting segmentation fault. I cannot figure out how. Can someone help ?