AVL Tree node deletion - c++

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 ?

Related

Deleting a node in a binary search tree

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

Inserting into a Binary Tree (geeksforgeeks) recursively

I'm trying to implement the insertion function used on geeksforgeeks.com but am running into some problems trying to work it into my current code.
I have a vector with the data I need to put into the binary tree. I use this function to pass the numbers into the insertion function:
void populateTree(vector<string> dataVec) {
for (int i = 0; i < dataVec.size(); i++) {
insert(stoi(dataVec[i]), root);
}
}
This is the insertion function:
node* insert(int x, node* node) {
if (node == nullptr)
return newNode(x);
if (x < node->data)
node->left = insert(x, node->left);
else
node->right = insert(x, node->right);
return root;
}
New node function:
node* newNode(int num) {
node* temp = new node;
temp->data = num;
temp->left = temp->right = nullptr;
temp->level = 1;
return temp;
}
Root is a private member within the class which is initialized to nullptr. I'm not sure how I should go about making the first node that comes in from the vector as the root and then keep inserting things beginning from there recursively. Thanks!
The problem in your is related to use of pointer.
Instead of using node* insert(int x, node* node) you should use node* insert(int x, node** node) or node* insert(int x, node*& node) and adopt your code accordingly.
Following is corrected sample code. See it in execution here:
#include <iostream>
#include <vector>
using namespace std;
struct Node
{
int val;
Node* left;
Node* right;
Node(int v)
{
val = v;
left = right = nullptr;
}
};
class Tree
{
Node* root;
Tree()
{
root = nullptr;
}
public:
static void insert(int x, Node*& node)
{
if (node == nullptr)
{
node = new Node(x);
}
else
{
if (x < node->val)
insert(x, node->left);
else
insert(x, node->right);
}
}
static Tree* populateTree(vector<string> dataVec)
{
Tree* t= new Tree();
for (int i = 0; i < dataVec.size(); i++)
{
insert(stoi(dataVec[i]), t->root);
}
return t;
}
static void printTree(Node* node, string s)
{
if(node == nullptr) return;
cout<<s<< "+"<<node->val <<endl;
s += "----";
printTree(node->left,s);
printTree(node->right, s);
}
static void printTree(Tree* t)
{
if(t)
{
printTree(t->root, "");
}
}
};
int main() {
Tree* t = Tree::populateTree({"70", "2", "7", "20", "41", "28", "20", "51", "91"});
Tree::printTree(t);
return 0;
}

problems in implementation of avl

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;
}

AVL Trees and Doubly Linked Lists

so, I am really new to programming, and I am taking a c++ class right now, in which I need to write and implement and AVL Tree, using a Doubly Linked lists to print off the contents of my tree, level by level. The teacher is really picky, so we can't use any containers from the standard libraries. My Doubly Linked list should be working fine, because I used it on a previous project, but I am getting an error when trying to combine it with the AVL Tree. I know my code probably has A LOT of things that need to be modified, but one step at a time. I am getting the following error, so I was wondering if you guys could help me figure out how to fix it. Also, if you have any suggestions on how to better my code, I would appreciate it.
In instantiation of ‘void AVLTreeSet::print(std::ofstream&) [with ItemType = std::basic_string; std::ofstream = std::basic_ofstream]’:
Lab6/main.cpp:80:20: required from here
Lab6/AVLTreeSet.h:152:49: error: cannot convert ‘LinkedList >::AVLNode*>::Node*’ to ‘AVLTreeSet >::AVLNode*’ in initialization
AVLNode* n = MyList.remove(i);
This is my AVLTree.h:
#pragma once
#include <fstream>
#include "LinkedList.h"
using namespace std;
template <typename ItemType>
class AVLTreeSet {
struct AVLNode {
ItemType item;
int height;
AVLNode* left;
AVLNode* right;
AVLNode(const ItemType& _item, AVLNode* _left = NULL, AVLNode* _right = NULL, int _height = 0) :
item(_item), left(_left), right(_right), height(_height) {}
};
AVLNode* root;
int size = 0;
public:
void RemoveBelowRoot(AVLNode *& n, const ItemType& item)
{
if (n == NULL)
{
return;
}
else if(item < n->item)
{
RemoveBelowRoot(n->left, item);
}
else if(item > n->item)
{
RemoveBelowRoot(n->right, item);
}
else if(n->left == NULL)
{
n = n->right;
}
else if (n->right == NULL)
{
n = n->left;
}
else
{
n = findMin(n->right);
RemoveBelowRoot(n->right, n->item);
}
balance(n);
size--;
// update height of nodes on this path
}
AVLNode * findMin(AVLNode* n)
{
if (n == NULL)
{
return n;
}
else if (n->left->item < n->item)
{
findMin(n->left);
}
else if(n->left->item > n->item)
{
findMin(n->right);
}
return n;
}
void remove(const ItemType& item) {
RemoveBelowRoot(root, item);
}
bool find(const ItemType& item) {
if (findBelowRoot(root, item))
{
return true;
}
return false;
}
bool findBelowRoot(AVLNode * n, const ItemType& data)
{
if (n->item == data)
{
return true;
}
else if (data > n->item)
{
findBelowRoot(n->right, data);
}
else if (data < n->item)
{
findBelowRoot(n->left, data);
}
}
void clear()
{
while (getHeight(root) != 0)
{
// remove
}
}
void addBelowRoot(AVLNode *& n, const ItemType& item)
{
if (n == NULL)
{
n = new AVLNode(item);
size++;
}
else if (item < n->item)
{
addBelowRoot(n->left, item);
}
else if(item > n->item)
{
addBelowRoot(n->right, item);
}
}
void add(const ItemType& item) {
addBelowRoot(root, item);
}
void print (ofstream& out)
{
if (root == NULL)
{
return;
}
else {
LinkedList<AVLNode *> MyList;
MyList.insert(0, root); // add root to Q
while (MyList.getSize() != 0) // While Q is not empty
//(figure out how many items are in that level)(levelsize = Q.size();)
{
for (auto i = 0; i < MyList.getSize(); i++) // for (int 1 = 0; i < LEVELSIZE; i++)
{
AVLNode* n = MyList.remove(i);
out << "level " << i << " " << n->item << "(" << n->height << ") ";
if (n->left != NULL) {
MyList.insert(MyList.getSize(), n->left);
}
if (n->right != NULL) {
MyList.insert(MyList.getSize(), n->right);
}
}
}
out << "\n ";
}
}
void balance (AVLNode *n)
{
if (getHeight(n->left) - getHeight(n->right))
{
balanceToRight(n);
}
if (getHeight(n->right) - getHeight(n->left))
{
balanceToLeft(n);
}
}
int getHeight(AVLNode *& n)
{
if (n == NULL)
{
return 0;
}
else
{
return n->height;
}
}
void balanceToRight(AVLNode * n)
{
if (getHeight(n->left->right) > getHeight(n->left->left))
{
rotateLeft(n->left);
}
rotateRight(n);
}
void rotateRight(AVLNode *&n)
{
AVLNode * k = n->left;
n->left = k->right;
k->right = n;
n = k;
// update heights of k and n
}
void rotateLeft(AVLNode *& n)
{
AVLNode * k = n->right;
n->right = k->left;
k->left = n;
n = k;
// update heights of k and n
}
void balanceToLeft(AVLNode * n)
{
if (getHeight(n->right->left) > getHeight(n->right->right)) // check with TAs if this is right
{
rotateRight(n);
}
rotateLeft(n);
}
/*void updateHeight(AVLNode *& n)
{
}*/
};
Now this is my LinkedList.h
#pragma once
#include <iostream>
#include <cstddef>
#include <fstream>
using namespace std;
template <typename ItemType>
class LinkedList {
struct Node {
ItemType item;
Node *next;
Node *prev;
Node(const ItemType &_item, Node *_next = NULL, Node *_prev = NULL) :
item(_item), next(_next), prev(_prev) { }
};
Node *head;
Node *tail;
int size = 0;
public:
~LinkedList()
{
clear();
}
void insert(int index, ItemType& item) {
if (index > size || size < 0)
{
return;
}
Node * newNode = new Node(item);
if (size == 0)
{
head = newNode;
tail = newNode;
newNode->next = NULL;
newNode->prev = NULL;
size++;
}
else if (index == 0)
{
head->prev = newNode;
newNode->next = head;
head = newNode;
size++;
}
else if (index == size) //INSERTING AT THE END
{
newNode->prev = tail;
newNode->next = NULL;
tail->next = newNode;
tail = newNode;
size++;
}
else {
Node* n = find_node(index);
newNode->next = n;
newNode->prev = n->prev;
n->prev->next = newNode;
n->prev = newNode;
size++;
}
}
Node * remove(int index) {
if (head == NULL || index >= size || index < 0)
{
return NULL;
}
else {
Node* name = find_node(index);
Node * n;
if (size == 1) // REMOVE THE ONLY NODE
{
n = head;
head = NULL;
tail = NULL;
size--;
}
else if (index == 0) //REMOVE THE FIRST NODE WHEN THERE'S MORE THAN ONE IN THE LIST
{
n = head;
head = head->next;
head->prev = NULL;
size--;
}
else if (index == size-1) //REMOVE THE LAST WHEN THERE'S MORE THAN ONE NODE IN THE LIST
{
n = tail;
tail = n->prev;
tail->next = NULL;
size--;
}
else
{
n = find_node(index);
n->prev->next = n->next;
n->next->prev = n->prev;
size--;
}
delete n;
return name;
}
}
Node * find_node(int index)
{
Node * n = NULL;
if (0 <= index && index <= size/2)
{
n = head;
for (int i = 0; i < index; i++)
{
n = n->next;
}
}
else if (size/2 < index && index <= size-1)
{
n = tail;
for (unsigned i = size-1; i > index; i--)
{
n = n->prev;
}
}
return n;
}
int getSize()
{
return size;
}
/* void print(LinkedList <string>& list, ofstream& out, int i)
{
if(head == NULL)
{
return;
}
out << "node " << i << ": " << getItem(i) << "\n";
}
Node* getItem(const int index)
{
if (index > size)
{
return NULL;
}
Node* temp = head;
for (unsigned i = 0; i < size; i++)
{
if (i == index)
{
return temp;
}
temp = temp-> next;
}
return NULL;
}*/
/* int find(const ItemType& item) {
Node * NodeP = head;
for (unsigned i = 0; i < size; i++)
{
if (NodeP->item == item)
{
return i;
}
NodeP = NodeP->next;
}
return -1;
}*/
void clear()
{
while (size != 0){
remove(0);
}
}
};
Thanks so much!
LinkedList::remove returns a LinkedList::Node pointer. You are trying to assign that into an AVLTreeSet::AVLNode pointer.
The AVLTreeSet::AVLNode * you are looking for is in the item member of the returned Node pointer.
You could do something like:
LinkedList<AVLNode *>::Node* n = MyList.remove(i);
AVLNode *treeNode = n->item;
Notes
You should be checking for NULL as the return value for remove, if it doesn't find anything.
remove actually deletes the node then returns it. You are then accessing something that has been deleted, which is Undefined Behavior. You really need to fix this before you go much further.
your for loop will only remove about half of the objects, as your are removing items from the list while still iterating further along the list using i.

AVL Tree Compiles and Runs But Crashes Instantly

So the program I have here will compile however it will crash instantly if I create a class object. What I mean is, in my main.cpp if I create say "AVLTree obj;" The program crashes....
If I leave that out then everything is fine... Any help would be appreciated.
Thank You. // MAIN below
using namespace std;
int main()
{
cout << "******************************" << endl;
cout << " Self Balancing AVL Tree " << endl;
cout << "******************************" << endl;
/** AVLtree obj;
obj.insert(100);
obj.insert(20);
obj.insert(25);
obj.insert(200);
assert isEmpty();
obj.preOrderPrint(*root);
obj.inOrderPint(*root);
obj.postOrderPrint(*root);
obj.remove(20);
*/
return 0;
}
HEADER
#ifndef AVLTREE_H
#define AVLTREE_H
//Moved this outside of the class trying to get things running
struct TreeNode
{
int key;
int data;
TreeNode *parent;
TreeNode *right;
TreeNode *left;
char factor; //byte
};
//-------------------------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------------------- s
class AVLtree
{
private:
protected:
//neccessary tree nodes
TreeNode *root;
TreeNode *tmp, *node;
TreeNode *holder1, *holder2, *holder3, *newnode;
int tmpdata;
bool h;
int height(TreeNode * pos) const;
int max(int a, int b) const;
//Rotate functions broken up individually and used within the
//insert function. Was having pointer issues when insert was
//all one function
TreeNode * singleRotateLeft(TreeNode *holder2);
TreeNode * singleRotateRight(TreeNode *holder2);
TreeNode * doubleRotateLeft(TreeNode *holder2);
TreeNode * doubleRotateRight(TreeNode *holder2);
TreeNode * _insert(int key, TreeNode * node);
TreeNode * _remove(int key, TreeNode * node);
public:
AVLtree();
void insert(int key, int data);
bool isEmpty();
void remove(int key);
int retrieve(int key);
void preOrderPrint(TreeNode *root)const;
void inOrderPrint(TreeNode *root)const;
void postOrderPrint(TreeNode *root)const;
int size;
};
#endif // AVLTREE_H
CPP for HEADER
#include "avltree.h"
#include <cstdio>
#include <iostream>
using namespace std;
//-------------------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------------------
AVLtree::AVLtree()
{
size = 0;
//Initialize values
root = NULL;
root->left = NULL;
root->right = NULL;
root->parent = NULL;
}
//-------------------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------------------
int AVLtree::retrieve(int key)
{
//height of 0 means the tree must be empty
if(size == 0)
{
return NULL;
}
tmp = root;
//While not empty search both sides of tree for key
while(tmp != NULL)
{
if(key < tmp->key)
tmp = tmp->left;
else if(key > tmp->key)
tmp = tmp->right;
else
return tmp->data;
}
return NULL;
}
//Simple bool determining if the tree is empty via the root
bool AVLtree::isEmpty()
{
if(root == NULL)
{
cout << "The Tree Is Empty!! " << endl;
return true;
}
else
{
cout << "The Tree Is NOT Empty" << endl;
return false;
}
}
//-------------------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------------------
int AVLtree::height( TreeNode * pos ) const
{
if( pos == NULL )
return -1;
else
return pos->factor;
}
//-------------------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------------------
int AVLtree::max( int a, int b ) const
{
return a > b ? a : b;
}
//-------------------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------------------
TreeNode * AVLtree::singleRotateLeft(TreeNode *holder2)
{
holder1 = holder2->left;
holder2->left = holder1->right;
holder1->right = holder2;
holder2->factor = max(height(holder2->left), height(holder2->right))+1;
holder1->factor = max(height(holder1->left), holder2->factor)+1;
return holder1; // new root
}
//-------------------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------------------
TreeNode * AVLtree::singleRotateRight(TreeNode *holder1)
{
holder2 = holder1->right;
holder1->right = holder2->left;
holder2->left = holder1;
holder1->factor = max(height(holder1->left), height(holder1->right))+1;
holder2->factor = max(height(holder2->right), holder1->factor)+1;
return holder2; // new root
}
//-------------------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------------------
TreeNode * AVLtree::doubleRotateLeft(TreeNode *holder3)
{
holder3->left = singleRotateRight(holder3->left);
return singleRotateLeft(holder3);
}
//-------------------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------------------
TreeNode * AVLtree::doubleRotateRight(TreeNode *holder1)
{
holder1->right = singleRotateLeft(holder1->right);
return singleRotateRight(holder1);
}
//-------------------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------------------
void AVLtree::insert(int key, int data)
{
size++;
tmpdata = data;
root =_insert(key,root);
}
//-------------------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------------------
TreeNode * AVLtree::_insert(int key, TreeNode * node)
{
//Empty case, create a new tree
if (node == NULL)
{
node = new TreeNode;
node->factor = 0;
node->key = key;
node->data = tmpdata;
node->left = NULL;
node->right = NULL;
// if(size==1)
// root=node;
}
//Key is less than, move down the left child
else if(key < node->key)
{
node->left= _insert(key,node->left);
if(height(node->left) - height(node->right) == 2)
{
if(key < node->left->key)
node = singleRotateLeft(node);
else
node = doubleRotateLeft(node);
}
}
//Key is greater than move down the right child
else if(key > node->key)
{
node->right= _insert(key,node->right);
if(height(node->right) - height(node->left) == 2)
{
if(key > node->right->key)
node = singleRotateRight(node);
else
node = doubleRotateRight(node);
}
}
// node->factor=-1;
// if(node->left!=NULL)
// node->factor=node->left->factor;
// if(node->right!=NULL)
// node->factor=max(node->factor, node->right->factor);
node->factor = max(height(node->left ),height(node->right))+1;
return node;
}
//-------------------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------------------
void AVLtree::preOrderPrint(TreeNode *node) const
{
//Empty node returns out
if(node == NULL) return;
//print the contents of the node specified
cout << node->data << " ";
//Navigate and display left subtree
preOrderPrint(node->left);
//Followed by the right subtree
preOrderPrint(node->right);
}
void AVLtree::inOrderPrint(TreeNode *node) const
{
if(node == NULL) return;
inOrderPrint(node->left);
// Root middle value is displayed in the middle of the printing
//operation
cout << node->data << " ";
inOrderPrint(node->right); // Left childeren last to be printed
}
void AVLtree::postOrderPrint(TreeNode *node) const
{
if(node == NULL) return; // Empty tree returns
postOrderPrint(node->left); //Display left side subtree
postOrderPrint(node->right); // Followed by right side subtree
cout << node->data << " "; //Finish with root
}
void AVLtree::remove(int key)
{
root =_remove(key,root);
}
//-------------------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------------------
TreeNode * AVLtree::_remove(int key, TreeNode * node)
{
//temp bool determining state of removal
bool done = false;
//Empty case there is nothing to do, return done immediately
if (node == NULL)
{
h = false;
done = true;
}
else
//If key data is less than the current node
if (key < node->key) //delete from left subtree
{
newnode =_remove(key,node->left);
node->left = newnode;
if(h)
{
//Check for height imbalance
if(height(node->right) - height(node->left) == 2)
{
if(height(node->right) > height(node->left))
node = singleRotateLeft(node);
else
node = singleRotateRight(node);
}
node->factor = max(height(node->left ),height(node->right))+1;
if (node->factor >= 0)
{
node->factor = root->factor -1;
if (node->factor == -1)
h = false;
}
else if (node->right->factor == -1)
singleRotateRight(node);
else
singleRotateLeft(node);
done = true;
return node;
}
}
else if (key == node->key) //del node
{
if (node->left == NULL || node->right == NULL) // one or no children
{
if (node->left == NULL)
holder1 = node->right;
else
holder1 = node->left;
delete node;
h = true; done = true;
return(holder1);
}
else // both of children
{
holder2 = node->right;
while (holder2->left != NULL)
holder2 = holder2->left;
node->key = holder2->key;
key = node->key;
}
}
if (!done && key >= node->key) // delete from right subtree
{
newnode=_remove(key, node->right);
node->right = newnode;
if (h)
{
if(height(node->right) - height(node->left) == 2)
{
if(height(node->right) > height(node->left))
node = singleRotateLeft(node);
else
node = singleRotateRight(node);
}
node->factor = max(height(node->left ),height(node->right))+1;
//
/* if (node->factor <= 0)
{
node->factor=node->factor+1;
if (node->factor ==1)
h=false;
}
else if (node->right->factor==1)
singleRotateLeft(node);
else
singleRotateRight(node);*/
return node;
}
}
}
//-------------------------------------------------------------------------------------------------------------
//-------------------------------------------------------------------------------------------------------------
You don't think this code is a problem?
root = NULL;
root->left = NULL;
root->right = NULL;
root->parent = NULL;
Specifically, you're initializing your root node to null, then trying to assign values to root's properties. You can't dereference / assign values to a null pointer.