AVL failing to insert (c++) [closed] - c++

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
I've been working on implementing a normal binary search tree as well as an AVL tree. I've got it mostly figured out, but there's one problem I can't seem to resolve. When I compile and run the driver, the insert fails. No errors on run or compile; it simply doesn't insert. I've even pasted the code from my BST insert into the insert method with the same results. I'll put the implementation below, along with the BST implementation. Any help would be perfect! Forgive me for the semi-messy code. Haven't cleaned it up well yet.
BST Definition
class BSTree {
BSTNode *root;
public:
//constructors
BSTree();
BSTree(int);
//public members
bool isEmpty(); //check if the bst is empty
void insert(int newValue); //inserts an int into the bst. Returns success
bool find(int findMe); //searches bst for int. True if int is in tree
void preorder(); //calls recursive transversal
void inorder(); //calls recursive traversal
void postorder(); //calls recursive transversal
int height(BSTNode *n); // given node only.
int height(); //returns height of whatever node is passed in.
int totalheight(); //returns tot height. height of empty tree = -1
int avgheight(); //returns avg height of tree
int totaldepth(); //returns tot depth. depth of empty tree = -1
int avgdepth(); //returns avg depth of tree
bool remove(int value); //deletes int. returns true if deleted
private:
int depth(BSTNode *n, int count); //depth of node. recursive.
int counter(BSTNode *n); //called by other functions for counting nodes
int totalheight(BSTNode *n); //called from public totalheight
int totaldepth(BSTNode *n, int depth);
int avgheight(BSTNode *n, int th);
bool findRecursive(struct BSTNode *root, int findMe); //called from public find
struct BSTNode* insertRecursive(struct BSTNode *n, int newValue);
void inorderRecursive(BSTNode *n); //traverses tree in inorder
void preorderRecursive(BSTNode *n); //traverses tree in preorder
void postorderRecursive(BSTNode *n); //traverses tree in preorder
};
//----------------------Constructor---------------------------
BSTree::BSTree(){
root = NULL;
} // BSTree
//root value given
BSTree::BSTree(int value){
root = new BSTNode(value);
} //BSTree(int)
//--------------------------insert-------------------------
void BSTree::insert(int newValue){
root = insertRecursive(root,newValue);
} //insert
struct BSTNode* BSTree::insertRecursive(struct BSTNode *n,int newValue){
//base case
if(n==NULL)
return new BSTNode(newValue);
else if (newValue < n->value) {
n->left = insertRecursive(n->left,newValue);
}
else if (newValue > n->value) {
n->right = insertRecursive(n->right,newValue);
}
else; //duplicate: do nothing
return n;
} //insertRecursive
//--------------------------Call in main-------------------------
BSTree *t = new BSTree();
t->insert(50);
Keep in mind, that works perfectly.
AVL
class AVLTree : public BSTree {
BSTNode *root;
public:
//constructors
AVLTree(); //given nothing
AVLTree(int value); //giving root value
//member methods
void insert(int newValue);
private:
struct BSTNode* insert(BSTNode *n, int newValue);
struct BSTNode* rotateLeft(BSTNode *n);
struct BSTNode* rotateRight(BSTNode *n);
struct BSTNode* doubleLeft(BSTNode *n);
struct BSTNode* doubleRight(BSTNode *n);
};
//--------------------------constructors-----------------------
AVLTree::AVLTree(){
root = NULL;
} // AVLTree
//root value given
AVLTree::AVLTree(int value){
root = new BSTNode(value);
} //AVLTree(int)
I won't show the rotate methods because even without them and the normal BST code in, it still doesn't work.
//------------------------------insert------------------------
void AVLTree::insert(int newValue){
root = insert(root, newValue);
}//insert
struct BSTNode* AVLTree::insert(BSTNode* n, int newValue){
if (n == NULL){ //if we are at end of tree. Insert.
return new BSTNode(newValue);
}//if
else if (newValue < n->value) { //move left if newValue smaller than n->value
n->left = insert(n->left,newValue);
if (height(n->left) - height(n->right) == 2){
if(newValue < n->left->value)
n = rotateLeft(n);
else
n = doubleLeft(n);
}//if == 2
}//else if
else if (newValue > n->value) { //move right if newValue bigger
n->right = insert(n->right,newValue);
if (height(n->right) - height(n->left) == 2){
if(newValue > n->right->value)
n = rotateRight(n);
else
n = doubleRight(n);
}//if == 2
}//else if
else; //duplicate. Do nothing.
n->height = max(height(n->left),height(n->right)) + 1;
return n;
}//insert
//--------------------call in main ---------------------------
AVLTree *a = new AVLTree();
a->insert(50);

You have two root variables.
Your AVLTree has its own root member variable, which is used in the methods of AVLTree.
However, the methods of BSTree use the root variable declared in BSTree.
Remove the unnecessary variable from AVLTree.

Related

Creating a binary Tree and search function

I am creating a binary tree and want to just Search function but I want to know how many nodes are visited to find a value. in the search function.
Here is the hearder file
#ifndef INTBINARYTREE_H
#define INTBINARYTREE_H
class IntBinaryTree
{
private:
struct TreeNode
{
int value; // The value in node .
TreeNode *left; //pointer to left node
TreeNode *right; // Pointer to right child node
};
TreeNode *root;
//private member functions
void insert(TreeNode *&,TreeNode *&);
void displayInOrder(TreeNode *) const;
void displayPreOrder(TreeNode *) const;
void displayPostOrder(TreeNode *) const;
public:
IntBinaryTree()
{
root = nullptr;
}
// Binary search tree
int searchNode(int);
void insertNode(int);
void displayInOrder() const
{
displayInOrder(root);
}
#endif // INTBINARYTREE_H
And here is the .cpp File I want to know how to for the search function if a value is not found zero and if value is found how many nodes are visited ?
#include "IntBinaryTree.h"
void IntBinaryTree::insert(TreeNode *&nodePtr, TreeNode *&newNode)
{
if (nodePtr == nullptr)
nodePtr=newNode; // insert the node
else if (newNode->value < nodePtr->value) `//search the left branch`
insert(nodePtr->left, newNode);
else
insert(nodePtr->right, newNode); //search the right branch
}
void IntBinaryTree::insertNode(int num)
{
TreeNode *newNode= nullptr; // pointer to a new node
//create a new node and store num in it
newNode = new TreeNode;
newNode->value= num;
newNode->left = newNode->right = nullptr;
//insert the node
insert(root, newNode);
}
int IntBinaryTree::searchNode(int num)
{
TreeNode *nodePtr = root;
while(nodePtr)
{
if (nodePtr->value==num)
{
cout<<"Node found"<<num<<endl;
}
else if (num < nodePtr->value)
nodePtr = nodePtr->left; // look to the left side of the branch if less than the value of the node
else
nodePtr = nodePtr->right; // look to the right side of the if not less than the value .
}
return 0;
}
Here is the Mainfile
#include <iostream>
#include "IntBinaryTree.h"
using namespace std;
int main()
{
IntBinaryTree tree;
cout << "inserting nodes" << endl;
tree.insertNode(5);
tree.insertNode(8);
tree.insertNode(3);
tree.insertNode(12);
tree.insertNode(9);
cout << "Done.\n";
tree.searchNode(5);
return 0;}
Can you please code it for me and edit and explain it briefly how does it work ?
Your includes are wrong.
There is a #include "IntBinaryTree.cpp" in your main.cpp. Because of this the insert member (and many others) exist twice. General rule: Never include cpp files.
Just remove the line, and you should be fine.

sum of left leaf nodes in a binary tree

This solution shows me segmentation fault, though it works fine for all the trees I tried. can anyone please help me detect the error.
code:
/*Structure of the node of the binary tree is as
struct Node
{
int data;
struct Node* left;
struct Node* right;
};
*/
// function should return the sum of all
// left leaf nodes
int sum=0,i=1;
Node* h;
int leftLeafSum(Node* root)
{
if(i==1)
{
h=root;
i--;
}
Node* temp=root;
if((temp->left!=NULL)&&(temp->left->left==NULL)&& (temp->left->right==NULL))
sum+=temp->left->data;
if(temp->left!=NULL)
leftLeafSum(temp->left);
if(temp->right!=NULL)
leftLeafSum(temp->right);
if(temp==h)
{
i=1;
int s=sum;
sum=0;
return s;
}
}
You need to check that the initial pointer is not equal to NULL:
int leftLeafSum(Node* root)
{
if (root==NULL)
return 0;
...
When I add this in, the website accepts the submission as being correct.

Depth-first binary search tree traversal to set all values of a tree?

So, I would wonder if it was easy to set all the values of a binary search tree in a simple inorder traversal, my thought being that since inorder traversal hits all the nodes anyway, and saves them in sorted order. Why not make it a generalized 'traverse' function that sets all the values, for instantaneous access later on?
My question:
Is there a way to optimize this? Using iteration instead of recursion (edit: I know it is possible now, using a stack of pointers http://en.wikipedia.org/wiki/Tree_traversal#Implementations)
Can I modify it (or use a similar algorithm) to set successor, predecessor, or height of each node?
#include<iostream>
#include<list>
using namespace std;
class Node{
public:
Node* left;
Node* right;
Node* parent;
int data;
int level;
bool isLeafNode;
bool isLeftChild;
bool hasLeftChild;
bool hasRightChild;
bool hasSibling;
public: Node(int x){
right=NULL;
left=NULL;
parent=NULL;
data = x;
level=0;
isLeafNode=false;
isLeftChild=true;
hasLeftChild=false;
hasRightChild=false;
hasSibling=false;
}
};
class BinarySearchTree{
public:
Node* root;
list<int> inorder;
int total; //total number of nodes
int depth; //maximum level of any node in tree. Level of root is zero
int total_leaf_nodes; //total number of leaf nodes
int total_non_leaf_nodes;
public: BinarySearchTree(){
root=NULL;
total=0;
depth=0;
total_leaf_nodes=0;
total_non_leaf_nodes=0;
}
void traverse(Node* p, int level){ //reset inorder, pass (root,0) to call.
//go left i.e. 'L'
if(p->left!=NULL) traverse(p->left, level+1);
//visit Node i.e. 'V'
total++;
inorder.push_back(p->data); //pushes to last position
p->level=level;
if(level > depth) depth=level;
if(p->left==NULL && p->right==NULL){
p->isLeafNode=true;
total_leaf_nodes++;
}
else{
total_non_leaf_nodes++;
if(p->left!=NULL)p->hasLeftChild=true;
if(p->right!=NULL){
p->hasRightChild=true;
(p->right)->isLeftChild=false;
}
if(p->left!=NULL && p->right!=NULL){
(p->left)->hasSibling=true;
(p->right)->hasSibling=true;
}
}
//go right i.e. 'R'
if(p->right!=NULL) traverse(p->right, level+1);
}
};

Problems with rotations when converting a BST (no recursion) to AVL

I'm working on a university project (Data structures) this weekend and I have to code an AVL tree in C++. I thought that it wouldn't be difficult to code a BST first and then convert it into an AVL. Probably I was wrong... I have two classes, class node and class AVLTree,which is friend of class node. I managed to do the insertions and deletions according to BST's rules (I checked) and also I managed to find the balance factor of its node of the tree (which also worked). However, when I tried the simple left rotations, everything went out of order! Here's my code (first the .h files):
class node
{
public:
node();
private:
int data;
int heightL;
int heightR;
int balance;
node* leftChild;
node* rightChild;
friend class AVLTree; //Only class AVLTree has now access to the private fields of class node
};
class node;
class AVLTree
{
public:
AVLTree();
bool insertNode(int aData);
node* searchNode(int key);
bool deleteNode(int key);
node* findMostLeft(node *aRoot);
node* findMostRight(node *subtree);
void display();
private:
node *root;
void inOrderTraversal(node* pointer);
node* newNode(int aData);
void updateHeightsInserting(int nodeCounter,int aData);
void updateHeightsDeleting(int nodeCounter,int aData);
void updateTreeHeights(node *ptr);
int max(int a,int b);
void balanceTree(node *current,node *previous,node *next);
void slRotation(node* current,node *previous,node *next);
void srRotation(node* current,node *previous,node *next);
void dlRotation(node* current,node *previous,node *next);
void drRotation(node* current,node *previous,node *next);
};
And now the .cpp file of class AVLTree (some methods only)
bool AVLTree::insertNode(int aData)
{
node *current,*next,*ptr;
bool isLeftChild;
int nodeCounter=0;
current=next=root;
ptr=newNode(aData);
if(ptr==NULL) //Couldn't allocate memory
{
return false;
}
if(current==NULL) //Inserting the first node in our tree (root==NULL)
{
root=ptr;
return true; //Successful insertion of root
}
do
{
if(aData<current->data) //If the node we want to insert has data smaller than the current node's data, then repeat the procedure for the left child of the current node
{
next=current->leftChild;
isLeftChild=true;
nodeCounter++;
}
else if(aData>current->data) //If the node we want to insert has data bigger than the current node's data, then repeat the procedure for the right child of the current node
{
next=current->rightChild;
isLeftChild=false;
nodeCounter++;
}
if(next==NULL)
{
if(isLeftChild)
{
current->leftChild=ptr;
}
else
{
current->rightChild=ptr;
}
updateHeightsInserting(nodeCounter,aData);
return true;
}
current=next; //Repeat the procedure for the next node
}while(next!=NULL); //Repeat the procedure until there's no next node, meaning we enter the if(next==NULL) statement
}
The method for updating heights:
void AVLTree::updateHeightsInserting(int nodeCounter,int aData)
{
node *current,*next,*previous;
current=next=previous=root;
do
{
if(aData<current->data)
{
if(current->heightL<nodeCounter)
{
current->heightL=nodeCounter;
}
next=current->leftChild;
nodeCounter--;
}
else if(aData>current->data)
{
if(current->heightR<nodeCounter)
{
current->heightR=nodeCounter;
}
next=current->rightChild;
nodeCounter--;
}
current->balance=current->heightR-current->heightL;
if(abs(current->balance)>1)
{
if(abs(next->heightR-next->heightL)<1) //We use <1, because the hight of the next node hasn't been increased yet-If the next node isn't problematic it means the current node is
balanceTree(current,previous,next);
}
previous=current;
current=next;
}while(next->data!=aData);
}
A trial code for rotation (It doesn't work!)
void AVLTree::slRotation(node *current,node *previous,node *next)
{
if(current==root) //previous=current
{
node *temp;
root=next; //next=current->rightChild
temp=next->leftChild;
next->leftChild=current;
current->rightChild=temp;
}
else
previous->rightChild=next;
current->rightChild=NULL;
next->leftChild=current;
}
And the Balancing method:
void AVLTree::balanceTree(node *current,node *previous,node *next)
{
if(current->balance>1) //if the tree is right heavy
if(next->balance>0) //if the tree's right subtree is right heavy
slRotation(current,previous,next); //perform Simple Left Rotation
else //if the tree's right subtree is left heavy
dlRotation(current,previous,next); //perform Double Left Rotation
else //if the tree is left heavy
if(next->balance<0) //if the tree's left subtree is left heavy
srRotation(current,previous,next); //perform Simple Right Roation
else //if the tree's left subtree is right heavy
drRotation(current,previous,next); //perform Double Right Rotation
updateTreeHeights(root);
}
I also use the updateTreeHeights (this is tested, too and works well without the rotations) method here that isn't efficient, I know, but I didn't have a better idea!
void AVLTree::updateTreeHeights(node *ptr) //Visits the nodes by level recursively (post-order traversal), so that it can calculate the balance of each node
{
if(ptr==NULL)
return;
updateTreeHeights(ptr->leftChild);
updateTreeHeights(ptr->rightChild);
if(ptr->leftChild==NULL && ptr->rightChild==NULL)
{
ptr->heightL=ptr->heightR=0;
}
else if(ptr->leftChild==NULL)
{
ptr->heightR=max(ptr->rightChild->heightL,ptr->rightChild->heightR)+1;
ptr->heightL=0;
}
else if(ptr->rightChild==NULL)
{
ptr->heightL=max(ptr->leftChild->heightL,ptr->leftChild->heightR)+1;
ptr->heightR=0;
}
else
{
ptr->heightL=max(ptr->leftChild->heightL,ptr->leftChild->heightR)+1;
ptr->heightR=max(ptr->rightChild->heightL,ptr->rightChild->heightR)+1;
}
ptr->balance=ptr->heightR-ptr->heightL;
}
Sorry for the long post! It's the first time in my life I use an AVL tree, let alone programming it! Hope you can help!
Problem solved! I messed up with the right and left pointers in double rotations!

search in a binary tree

I have written the following function to search for a value in a binary tree storing integer values (the function is part of a larger program):
bool tree::search(int num) //the function belongs to class 'tree'
{
node *temp=head; //'head' is pointer to root node
while(temp!=NULL)
{
if(temp->data==num)
break;
if(num>temp->data)
temp=temp->right;
if(num<temp->data)
temp=temp->left;
}
if(temp==NULL)
return false;
else if(temp->data==num)
return true;
}
The problem is: when I search for a value present in the tree, it runs fine. But if I search for a value not present in the tree, the program just hangs, and I have to close it.
One more thing - I know we can implement the search function recursively by passing node *temp as an argument, instead of declaring it inside, and I have done so which caused the program to run correctly, but I want to know what is the problem in the above code.
I am giving the full program here, just in case it makes fault- finding easier( please note that I have written only two functions yet):
#include<iostream>
using namespace std;
struct node
{
int data;
node *left;
node *right;
};
class tree
{
public:
node *head; //pointer to root
int count; //stores number of elements in tree
tree();
void addnode(int);
void deletenode(int);
bool search(int);
int minimum();
int maximum();
void inorder();
void preorder();
void postorder();
void printtree();
int mthlargest(); //finds 'm'th largest element
int mthsmallest(); //finds 'm'th smallest element
void convert(); //converts binary tree to linked list
};
tree::tree()
{
head=NULL;
count =0;
}
void tree::addnode(int num)
{
node *temp= new node;
temp->data=num;
temp->left=NULL;
temp->right=NULL;
node **ptr=&head; //double pointer
while(*ptr!=NULL)
{
if(num>(*ptr)->data)
ptr=&((*ptr)->right);
if(num<(*ptr)->data)
ptr=&((*ptr)->left);
}
*ptr=temp;
}
bool tree::search(int num)
{
node *temp=head;
while(temp!=NULL)
{
if(temp->data==num)
break;
if(num>temp->data)
temp=temp->right;
if(num<temp->data)
temp=temp->left;
}
if(temp==NULL)
return false;
else if(temp->data==num)
return true;
}
int main()
{
tree ob;
ob.addnode(2);
ob.search(2);
ob.search(3);
ob.search(-1);
ob.search(2);
cout<<endl<<endl;
system("pause");
return 0;
}
Side note : I am using Dev C++ compiler and Windows 7 OS.
Put an else and your problem will disappear.
Because after temp = temp->right; you must check temp again but in your original code you immediately test temp->data which may not be a valid pointer.
bool tree::search(int num)
{
node *temp = head;
while (temp != NULL)
{
if (temp->data == num)
break;
if (num > temp->data)
temp = temp->right;
else // <--- Put this 'else' here
if (num < temp->data)
temp = temp->left;
}
if (temp == NULL)
return false;
if (temp->data == num)
return true;
return false;
}
std::set
Use a std::set; it is basically STL's binary tree. If you want to search for something, you would use count, find or lower_bound.
Implementing basic data structures are good exercises, but in production, try to use STL first, as they are implemented by professionals with specific knowledge of the compiler/platform in question. Boost is another great set of data structures and common idioms.