I am using the Following code to Implement the AVL Tree Insertion but its not display in proper order nor its updating height I also left some function because when insertion completed than i will be able to complete those fucntions
AVLNode.cpp
#include <iostream>
#include <string>
#include "AVLNode.h"
using namespace std;
AVLNode::AVLNode(string ss, string na){
ssn = ss;
name = na;
height = 0;
left = NULL;
right = NULL;
parent = NULL;
}
AVLNode.h
#include <iostream>
#include <string>
using namespace std;
struct AVLNode{
string ssn;
string name;
AVLNode *left;
AVLNode *right;
AVLNode *parent;
int height;
AVLNode(string ss, string na);
};
AVLTree.cpp
#include <iostream>
#include <string>
#include <stdio.h>
#include "AVLTree.h"
#include <iomanip>
#include <queue>
using namespace std;
AVLTree::AVLTree(){
root = NULL;
}
AVLTree::~AVLTree(){
}
AVLNode* AVLTree::getRoot(){
return root;
}
// search value ss in the AVL tree
bool AVLTree::find(string ss){
if (root == NULL) {
return false;
}
AVLNode* node = root;
while (node != NULL) {
if (ss.compare(node->ssn) == 0) {
return true;
}
if (ss.compare(node->ssn) < 0) {
node = node->left;
}
else{
node = node->right;
}
}
return false;
}
// return the height of the subtree rooted at node
// if subtree is empty, height is -1
// if subtree has one node, height is 0
int AVLTree::height(AVLNode* node){
if(node != NULL){
return node->height;
}
else{
return -1;
}
}
// return the balance factor of the node
int AVLTree::balanceFactor(AVLNode* node){
return height(node->left) - height(node->right);
}
// update the height of the node
// this should be done whenever the tree is modified
void AVLTree::updateHeight(AVLNode* node){
int hl = height(node->left);
int hr = height(node->right);
node->height = (hl > hr ? hl : hr) + 1;
}
// rotate right the subtree rooted at node
// return the new root of the subtree
AVLNode* AVLTree::rotateRight(AVLNode* node){
AVLNode* lp = node->left; // left child of node
if (node->parent != NULL) { // node is not root
if (node->parent->left == node) { // node is a left child
node->parent->left = lp;
}else{
node->parent->right = lp; // node is a right child
}
}
if (lp->right != NULL) { // pointer update
lp->right->parent = node;
}
lp->parent = node->parent;
node->left = lp->right;
lp->right = node;
node->parent = lp;
updateHeight(node); // after rotation, update height
updateHeight(lp); // after rotation, update height
if (node == root) {
root = lp;
}
return lp; // lp is the new root of the subtree
}
// rotate left the subtree rooted at node
// return the new root of the subtree
AVLNode* AVLTree::rotateLeft(AVLNode* node){
AVLNode* rp = node->right;
if (node->parent!=NULL) {
if (node->parent->left == node) {
node->parent->left = rp;
}else{
node->parent->right = rp;
}
}
if (rp->left != NULL) {
rp->left->parent = node;
}
rp->parent = node->parent;
node->right = rp->left;
rp->left = node;
node->parent = rp;
node->parent = rp;
updateHeight(node);
updateHeight(rp);
if (node == root) {
root = rp;
}
return rp;
}
// rebalance a tree rooted at node
// return the new root of the subtree
AVLNode* AVLTree::balance(AVLNode* node){
updateHeight(node);
if (balanceFactor(node) == 2) {
if (balanceFactor(node->left) < 0) {
node->left = rotateLeft(node->left); // for left right case
}
AVLNode* temp = rotateRight(node);
updateHeight(temp);
return temp;
}
if (balanceFactor(node) == -2) {
if (balanceFactor(node->right) > 0) {
node->right = rotateRight(node->right); // for right left case
}
AVLNode* temp2 = rotateLeft(node);
updateHeight(temp2);
return temp2;
}
return node;
}
// insert a new node with (ss, na) to the AVL tree
// if there exists ss value, return false
// otherwise, insert it, balance the tree, return true
bool AVLTree::insert(string ss, string na){
AVLNode *newNode=new AVLNode(ss,na);
AVLNode *Iterator;
if(root==NULL){
cout<<"Root Node Inserted"<<endl;
root=newNode;
} else {
Iterator = root;
int rootTempValue = atoi((Iterator->ssn).c_str());
int addTempValue = atoi((newNode->ssn).c_str());
if(rootTempValue <= addTempValue ){
// Right Portion of the tree
while(Iterator->right != NULL){
cout << "In the Right portion" <<endl;
int rootTempValue2 = atoi((Iterator->right->ssn).c_str());
int addTempValue2 = atoi((newNode->ssn).c_str()) ;
if(rootTempValue2 <= addTempValue2 )
Iterator = Iterator->right;
else
Iterator = Iterator->left;
//Iterator = Iterator->right;
}
Iterator->right = newNode ;
newNode->parent = Iterator ;
} else {
// Left Portion of the tree
while(Iterator->left != NULL){
//Iterator = Iterator->left;
int rootTempValue2 = atoi((Iterator->left->ssn).c_str());
int addTempValue2 = atoi((newNode->ssn).c_str()) ;
if(rootTempValue2 <= addTempValue2 )
Iterator = Iterator->right;
else
Iterator = Iterator->left;
}
newNode->parent = Iterator;
newNode->right = NULL ;
newNode->left = NULL;
Iterator->left = newNode ;
cout << "In the left portion : " <<Iterator->left->ssn<<endl;
}
}
balance(newNode);
updateHeight(newNode);
return true;
}
AVLNode* AVLTree::maxOfSubtree(AVLNode* node){
if (node == NULL) {
return NULL;
}
while (node->right != NULL) {
node = node->right;
}
return node;
}
// delete the node containing value ss
// if there is not such node, return false
// otherwise, delete the node, balance the tree, return true
bool AVLTree::deleteNode(string ss){
// please implement here
return true;
}
// internal function
// do not call it directly
void AVLTree::print(AVLNode* x, int indent){
if(x == NULL)
return;
if (x->right != NULL) {
print(x->right, indent+4);
}
if (indent != 0) {
cout << std::setw(indent) << ' ';
}
if(x->right != NULL){
cout << " /\n" << std::setw(indent) << ' ';
}
cout << x->ssn << endl;
if (x->left != NULL) {
cout << std::setw(indent) << ' ' <<" \\\n";
print(x->left, indent+4);
}
}
// print out the structure of the binary tree
// use it for debugging, I love this function
void AVLTree::print(){
int count = 0;
print(root, count);
}
// it does not level order traversal
// it prints out the number of node
// use it mainly for debugging
void AVLTree::levelOrder(){
// please implement it
}
main.cpp
#include <iostream>
#include "AVLTree.h"
int main(int argc, char** argv) {
AVLTree temp;
temp.insert("05", "a");
temp.insert("04", "b");
temp.insert("09", "c");
//temp.insert("03", "d");
//temp.insert("06", "d");
// temp.insert("07", "d");
//temp.insert("02", "d");
temp.print();
cout<<endl;
cout<<"The Height Of The Tree is :" << temp.height(temp.getRoot())<<endl;
cin.get();
return 0;
}
Your AVLTree has a complex class invariant and expressing it is generally a good idea for an efficient debug.
If you write a method like
bool
AVLTree::invariant() const {
if (root == NULL)
return true;
std::stack<AVLNode*> stack;
stack.push_back(root);
while (!stack.empty()) {
AVLNode* currentNode = stack.back();
int leftHeight = -1, rightHeight = -1;
if (currentNode->left) {
leftHeight = currentNode->left->height;
if (currentNode->left->parent != currentNode)
return false;
if (currentNode->left.height+1 != currentNode->height)
return false;
}
if (currentNode->right) {
rightHeight = currentNode->right->height;
if (currentNode->left->parent != currentNode)
return false;
if (currentNode->left.height+1 != currentNode->height)
return false;
}
if (leftHeigth > rightHeigth+1 || rightHeight > leftHeight+1)
return false;
if (currentNode->left)
stack.push_back(currentNode->left);
else {
do {
stack.pop_back();
AVLNode* parentNode = !stack.empty() ? stack.back() : NULL;
if (currentNode && parentNode->right != currentNode && parentNode->right) {
stack.push_back(parentNode->right);
break;
};
currentNode = parentNode;
} while (currentNode);
};
};
return true;
}
you can then debug your main function by adding into it the following code
assert(temp.invariant());
temp.insert("05", "a");
assert(temp.invariant());
temp.insert("04", "b");
assert(temp.invariant());
temp.insert("09", "c");
assert(temp.invariant());
As soon as you have identified the insertion that fails, you just have to break on the return false; in the invariant method that is executed. At this point you should be able to understand the origin of the bug.
Why not just use a std::stack? Recursion is basically just looping off of the call stack as it is.
if (!root)
root = new AVLNode(ss, na);
else
{
AVLNode *current = root;
AVLNode *previous = NULL;
std::stack<AVLNode*> rstack;
while (current != NULL)
{
previous = current;
//Use String Compare instead of cast
if (ss.compare(current->ssn) < 0) //If ss less than current
...
rstack.push(previous);
}
...
...
while (!rstack.empty())
{
rstack.top() = balance(rstack.top());
rstack.pop();
}
}
Related
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;
}
Made an AVL tree and everything worked well until I tested it with a larger amount of inserts. Upon deletion of a node with two children the data field within the node that is "moved" gets a strange value. Wich I've learned is some undefined behavior in c++. I don't have a clue on how to go about it. What am I missing?
AVL_Tree.cpp
#include "AVL_Tree.h"
#include "stddef.h"
#include <stdexcept>
#include <iostream>
#include <algorithm>
/*
* Constructor for TreeNode
*/
AVL_Tree::TreeNode::TreeNode(const int& data)
: data(data), height(1), leftChild(NULL), rightChild(NULL){};
void AVL_Tree::TreeNode::printNodeValue()
{
std::cout << data << "\n";
}
void AVL_Tree::TreeNode::printTree(bool isRight, const std::string& indent)
{
if(rightChild != NULL)
{
rightChild->printTree(true, indent + (isRight ? " " : " | "));
}
std::cout << indent;
if(isRight)
{
std::cout << " /";
}
else
{
std::cout << " \\";
}
std::cout << "----- ";
printNodeValue();
if(leftChild != NULL)
{
leftChild->printTree(false, indent + (isRight ? " | " : " "));
}
}
void AVL_Tree::TreeNode::printTree()
{
if(rightChild != NULL)
{
rightChild->printTree(true, "");
}
printNodeValue();
if(leftChild != NULL)
{
leftChild->printTree(false, "");
}
}
/*
* Constructor for the AVL_Tree
*/
AVL_Tree::AVL_Tree()
{
this->root = NULL;
this->size = 0;
}
/**
* Destructor
*/
AVL_Tree::~AVL_Tree()
{
destruct(this->root);
}
/**
* Deletes TreeNode objects recursively
*/
void AVL_Tree::destruct(TreeNode* root)
{
if(root != NULL)
{
destruct(root->rightChild);
destruct(root->leftChild);
delete root;
root = NULL;
}
}
/**
*Removes specified node
*/
void AVL_Tree::deleteNode(const int& data)
{
TreeNode* temp = remove(this->root, data);
if(temp != NULL)
{
this->root = temp;
size--;
}
}
/**
*Adds new node to the tree by calling insert()
*/
void AVL_Tree::add(const int& data)
{
try
{
TreeNode* node = new TreeNode(data);
this->root = insert(this->root, node);
size++;
}
catch(std::string s)
{
std::cout << s << std::endl;
}
}
void AVL_Tree::print()
{
root->printTree();
}
/**
* Prints the tree in ascending order
*/
void AVL_Tree::inOrder(TreeNode* current)
{
if(current != NULL)
{
inOrder(current->leftChild);
std::cout << current->data << std::endl;
inOrder(current->rightChild);
}
}
/**
*Recursively traverse the tree to find the correct place for the new node and then
*returns the tree.
*/
AVL_Tree::TreeNode* AVL_Tree::insert(TreeNode* current, TreeNode* newNode)
{
if(current == NULL)
{
return newNode;
}
if(newNode->data < current->data)
{
current->leftChild = insert(current->leftChild, newNode);
}
else if(newNode->data > current->data)
{
current->rightChild = insert(current->rightChild, newNode);
}
else
{
throw std::string("Data already exist in tree");
}
//return current;
return balance(current);
}
/**
* Recursively finds the TreeNode that matches 'dataToRemove' and erase it from the tree then returns the new tree
*/
AVL_Tree::TreeNode* AVL_Tree::remove(TreeNode* current, const int& dataToRemove)
{
if(current == NULL)
{
return current;
}
if(dataToRemove < current->data)
{
current->leftChild = remove(current->leftChild, dataToRemove);
}
else if(dataToRemove > current->data)
{
current->rightChild = remove(current->rightChild, dataToRemove);
}
else //if(dataToRemove == current->data)
{
TreeNode* temp = NULL;
//No children
if(current->leftChild == NULL && current->rightChild == NULL)
{
delete current;
current = NULL;
}
//One child
else if(current->leftChild != NULL && current->rightChild == NULL)
{
temp = current->leftChild;
current->data = temp->data;
current->leftChild = remove(current->leftChild, temp->data);
}
else if(current->leftChild == NULL && current->rightChild != NULL)
{
temp = current->rightChild;
current->data = temp->data;
current->rightChild = remove(current->rightChild, temp->data);
}
//Two children
else if(current->leftChild != NULL && current->rightChild != NULL)
{
temp = findSuccessor(current->rightChild);
current->data = temp->data;
remove(current->rightChild, temp->data);
}
}
return balance(current);
}
/**
* Returns height of tree
*/
int AVL_Tree::height(TreeNode* current)
{
if(current == NULL)
{
return 0;
}
return current->height;
}
/**
* Returns the balance factor for the argument(TreeNode pointer)
*/
int AVL_Tree::getBalance(TreeNode* current)
{
if(current == NULL)
{
return 0;
}
return height(current->rightChild) - height(current->leftChild);
}
/**
* Sets the height of the specified TreeNode
*/
void AVL_Tree::fixHeight(TreeNode* current)
{
int hl = height(current->leftChild);
int hr = height(current->rightChild);
current->height = (hl > hr ? hl : hr) + 1;
}
/**
* Takes TreeNode pointer as arguement and balances the tree if it isn't NULL
*/
AVL_Tree::TreeNode* AVL_Tree::balance(TreeNode* current)
{
if (current != NULL) {
fixHeight(current);
if(getBalance(current) == 2)
{
if(getBalance(current->rightChild) < 0)
{
current->rightChild = rotateRight(current->rightChild);
}
return rotateLeft(current);
}
if(getBalance(current) == -2)
{
if(getBalance(current->leftChild) > 0)
{
current->leftChild = rotateLeft(current->leftChild);
}
return rotateRight(current);
}
return current;
} else {
return NULL;
}
}
/**
* Preforms a left rotation
* Returns the rotated subtree
*/
AVL_Tree::TreeNode* AVL_Tree::rotateLeft(TreeNode* current)
{
TreeNode* right = current->rightChild;
current->rightChild = right->leftChild;
right->leftChild = current;
fixHeight(current);
fixHeight(right);
return right;
}
/**
* Preforms a right rotation
*/
AVL_Tree::TreeNode* AVL_Tree::rotateRight(TreeNode* current)
{
TreeNode* left = current->leftChild;
current->leftChild = left->rightChild;
left->rightChild = current;
fixHeight(current);
fixHeight(left);
return left;
}
/**
* Takes TreeNode pointer as argument and return the "leftest"(smallest) node in the right subtree.
*/
AVL_Tree::TreeNode* AVL_Tree::findSuccessor(TreeNode* current)
{
while(current->leftChild != NULL)
{
current = current->leftChild;
}
return current;
}
AVL_Tree.h
#ifndef AVLTREE_H
#define AVLTREE_H
#include <string>
class AVL_Tree
{
private:
struct TreeNode
{
TreeNode(const int& data);
int data;
int height;
TreeNode* leftChild;
TreeNode* rightChild;
void printTree(bool isRight, const std::string& indent);
void printTree();
void printNodeValue();
};
int size;
TreeNode* root;
TreeNode* findSuccessor(TreeNode* current);
TreeNode* remove(TreeNode* current, const int& dataToRemove);
TreeNode* insert(TreeNode* current, TreeNode* newNode);
int height(TreeNode* current);
TreeNode* balance(TreeNode* current);
int getBalance(TreeNode* current);
TreeNode* rotateLeft(TreeNode* current);
TreeNode* rotateRight(TreeNode* current);
void fixHeight(TreeNode* current);
void destruct(TreeNode* root);
TreeNode* findMin(TreeNode* current);
TreeNode* removeMin(TreeNode* current);
public:
AVL_Tree();
~AVL_Tree();
void deleteNode(const int& data);
void add(const int& data);
void print();
void inOrder(TreeNode* current);
};
#endif
main.cpp
#include "AVL_Tree.h"
#include <stdlib.h>
#include <vector>
using std::vector;
int main()
{
AVL_Tree at;
vector<int> list;
for(int i = 0; i < 20; i++)
{
int x = rand() % 100;
list.push_back(x);
at.add(x);
}
at.print();
at.add(list[0]);
at.print();
for(int i = 19; i >= 18; i--)
{
at.deleteNode(list[i]);
}
at.print();
return 0;
}
Output
output
If the data already exist in your tree, your code throws an exception. The calling code is assigning a pointer to a non returning function.
this->root = insert(this->root, node);
Test your code with some hard coded values and make sure to test with a duplicate value.
I'm writing a function that counts the leaf nodes of a height balanced tree using struct and pointers. The function takes 3 arguments: the tree, pointer to an array and the maximum depth of the tree. The length of the array is the maximum depth. When function is called the array is initialized to zero. The function recursively follows the tree structure,
keeping track of the depth, and increments the right counter whenever it reaches a leaf. The function does not follow any pointer deeper than maxdepth. The function returns 0 if there was no leaf at depth greater than maxdepth, and 1 if there was some pointer togreater depth. What is wrong with my code. Thanks.
typedef int object;
typedef int key;
typedef struct tree_struct { key key;
struct tree_struct *left;
struct tree_struct *right;
int height;
} tree_n;
int count_d (tree_n *tr, int *count, int mdepth)
{
tree_n *tmp;
int i;
if (*(count + 0) == NULL){
for (i =0; i<mdepth; i++){
*(count + i) = 0;
}
}
while (medepth != 0)
{
if (tr == NULL) return;
else if ( tree-> left == NULL || tree->right == NULL){
return (0);
}
else {
tmp = tr;
*(count + 0) = 1;
int c = 1;
while(tmp->left != NULL && tmp->right != NULL){
if(tmp-> left){
*(count + c) = 2*c;
tmp = tmp->left;
return count_d(tmp, count , mdepth);
}
else if(tmp->right){
*(count + c + 1) = 2*c + 1;
tmp = tmp->right;
return count_d(tmp,count, mdepth);
}
c++;
mpth--;
}
}
}
What is wrong with my code
One thing I noticed is that you are missing return in the recursive calls.
return count_d(tmp, count , mdepth);
// ^^^ Missing
There are two such calls. Make sure to add return to both of them.
Disclaimer: Fixing this may not fix all your problems.
Correct Function To Insert,Count All Nodes and Count Leaf Nodes
#pragma once
typedef int itemtype;
#include<iostream>
typedef int itemtype;
#include<iostream>
#include<conio.h>
#include<string>
using namespace std;
class Node
{
public:
Node* left;
Node* right;
itemtype data;
};
class BT
{
private:
int count = 0;
Node* root;
void insert(itemtype d, Node* temp);//Override Function
public:
BT();//Constructor
bool isEmpty();
Node* newNode(itemtype d);
Node* getroot();
void insert(itemtype d);//Function to call in main
int countLeafNodes(Node * temp);
int countAllNodes();//to count all nodes
}
BT::BT()//constructor
{
root = NULL;
}
bool BT::isEmpty()
{
if (root == NULL)
return true;
else
return false;
}
Node* BT::newNode(itemtype d)
{
Node* n = new Node;
n->left = NULL;
n->data = d;
n->right = NULL;
return n;
}
void BT::insert(itemtype d)//Function to call in main
{
if (isEmpty())
{
Node* temp = newNode(d);
root = temp;
}
else
{
Node* temp = root;
insert(d, temp);
}
count++;//to count number of inserted nodes
}
void BT::insert(itemtype d, Node* temp)//Private Function which is overrided
{
if (d <= temp->data)
{
if (temp->left == NULL)
{
Node* n = newNode(d);
temp->left = n;
}
else
{
temp = temp->left;
insert(d, temp);
}
}
else
{
if (temp->right == NULL)
{
temp->right = newNode(d);
}
else
{
temp = temp->right;
insert(d, temp);
}
}
}
int BT::countAllNodes()
{ return count; }
int BT::countLeafNodes(Node* temp)
{
int leaf = 0;
if (temp == NULL)
return leaf;
if (temp->left == NULL && temp->right == NULL)
return ++leaf;
else
{
leaf = countLeafNodes(temp->left) + countLeafNodes(temp->right);
return leaf;
}
}
void main()
{
BT t;
t.insert(7);
t.insert(2);
t.insert(3);
t.insert(15);
t.insert(11);
t.insert(17);
t.insert(18);
cout<<"Total Number Of Nodes:" <<t.countAllNodes() <<endl;
cout << "Leaf Nodes:" << t.countLeafNodes(t.getroot()) << endl;
_getch();
}
Output:
Ouput
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.
After a few questions and some nice answers and friendly helpers here. I got the sulotion to my porblem with the deleting in the binary tree, i got suggested that, i can not just delet the largest number in the tree cause its may not the last or it has childrens 1 ,2 or none, so i made the code down below, i used a lot commenting hope that can help you people help me. What i actually dont know now, is how do i call this RemoveLargest() function in my public and then later in main, even though i dont know if the code will run properly.
#include <iostream>
#include <string>
#include <cstdlib>
using namespace std;
template<class T>
class BinaryTree
{
struct Node
{
T data;
Node* lChildptr;
Node* rChildptr;
Node(T dataNew)
{
data = dataNew;
lChildptr = NULL;
rChildptr = NULL;
}
};
private:
Node* root;
void Insert(T newData, Node* &theRoot) //Insert elements into the tree start.
{
if(theRoot == NULL)
{
theRoot = new Node(newData);
return;
}
if(newData < theRoot->data)
Insert(newData, theRoot->lChildptr);
else
Insert(newData, theRoot->rChildptr);
} //end.
void PrintTree(Node* theRoot) //print me the tree /start
{
if(theRoot != NULL)
{
PrintTree(theRoot->lChildptr);
cout<< theRoot->data<<" \n";
PrintTree(theRoot->rChildptr);
}
} //end.
T Largest( Node* theRoot) // show me largest number /start.
{
if ( root == NULL )
{
cout<<"There is no tree";
return -1;
}
if (theRoot->rChildptr != NULL)
{
return Largest(theRoot->rChildptr);
}
T value = theRoot->data;
return value;
} //end.
void RemoveLargest(Node* theRoot) //remove the largest priority number from tree /start.
{
Node* current; //the current tree?
Node* parent; //the parent of the current node?
current=theRoot;
// 3 cases :
// 1. We're removing a leaf node
// 2. We're removing a node with a single child
// 3. we're removing a node with 2 children
//Node with single child.
if((current->lChildptr == NULL && current->rChildptr != NULL)||(current->lChildptr != NULL && current->rChildptr == NULL))
{
if(current->lChildptr == NULL && current->rChildptr != NULL)
{
if(parent->lChildptr==current)
{
parent->lChildptr = current->rChildptr;
delete current;
}
else
{
parent->rChildptr = current->rChildptr;
delete current;
}
}
else //left child ok, no right child
{
if(parent->lChildptr==current)
{
parent->lChildptr = current->lChildptr;
delete current;
}
else
{
parent->rChildptr = current->lChildptr;
delete current;
}
}
return;
}
//We found a leaf(a node with not a single child)
if(current->lChildptr == NULL && current->rChildptr == NULL)
{
if (parent->lChildptr == current)
parent->lChildptr = NULL;
else
parent->rChildptr = NULL;
delete current;
return;
}
//Node with 2 children
// replace node with smallest value in right subtree
if (current->lChildptr != NULL && current->rChildptr != NULL)
{
Node* checkr;
checkr = current->rChildptr;
if((checkr->lChildptr == NULL)&&(checkr->rChildptr == NULL))
{
current=checkr;
delete checkr;
current->rChildptr = NULL;
}
else //right child has children
{
//if the node's right child has a left child
//Move all the way down left to locate smallest element
if ((current->rChildptr)->lChildptr != NULL)
{
Node* lcurr;
Node* lcurrp;
lcurrp = current->rChildptr;
lcurr = (current->rChildptr)->lChildptr;
while(lcurr->lChildptr != NULL)
{
lcurrp = lcurr;
lcurr = lcurr->lChildptr;
}
current->data = lcurr->data;
delete lcurr;
lcurrp->lChildptr = NULL;
}
else
{
Node* temp;
temp = current->rChildptr;
current->data = temp ->data;
current->rChildptr = temp->rChildptr;
delete temp;
}
}
return;
}
};
public:
BinaryTree()
{
root = NULL;
}
void AddItem(T newData)
{
Insert(newData, root);
}
void PrintTree()
{
PrintTree(root);
}
T Largest()
{
return Largest(root);
}
void RemoveLargest()
{
RemoveLargest();
}
};
int main()
{
BinaryTree<int> *myBT = new BinaryTree<int>();
myBT->AddItem(5);
myBT->AddItem(1);
myBT->AddItem(4);
myBT->AddItem(2);
myBT->AddItem(3);
//for(int i = 0; i < 10; i++) //randommal tolti fel/fill with random
//myBT->AddItem(rand() % 100);
cout << "BinaryTree:" << endl; //kilistazaa a fat/ list my tree
myBT->PrintTree();
cout << "Largest element: " << myBT->Largest() << endl; //visszaadja a legnagyobb elemet/shows the largest number
myBT->RemoveLargest(); //suposed to delet the largest number
myBT->PrintTree(); //shows list again
}
edited the code, now its running, its creating the tree, shows the largest, but after i call my remove function still crashing... =/
Like I said before, I think you're making things overly complicated. You have to think of what it means that your node is the largest one, in the context of a binary search tree and the relationship between the keys in its nodes.
If a node is the largest one in the tree it cannot possibly have a right child pointer, because the right child would have to have a larger key. And then, if you know that it has at most a left child, you just replace your node with its possibly null left child, and you're done.
T ExtractLargest(Node*& n){
if (!n)
return -1;
if (n->rChildptr)
return ExtractLargest(n->rChildptr);
T result = n->data;
Node *d = n;
n = n->lChildptr;
delete d;
return result;
}