I have an AVL tree program that sorts a text file, stored as a string, using in-order traversal. This works as intended and is shown below
std::string fileName;
std::fstream readFile;
std::string storeFile;
struct Node
{
std::string key;
int height;
Node *left;
Node *right;
};
int max(int a, int b);
int height(Node *N)
{
if (N == NULL)
return 0;
return N->height;
}
int max(int lower, int upper)
{
return (lower > upper) ? lower : upper;
}
Node *newNode(std::string key)
{
Node *node = new Node();
node->key = key;
node->left = NULL;
node->right = NULL;
node->height = 1;
return node;
}
Node *rightRotation(Node *y)
{
Node *x = y->left;
Node *z = x->right;
x->right = y;
y->left = z;
y->height = max(height(y->left), height(y->right)) + 1;
x->height = max(height(x->left), height(x->right)) + 1;
return x;
}
Node *leftRotation(Node *x)
{
Node *y = x->right;
Node *z = y->left;
y->left = x;
x->right = z;
x->height = max(height(x->left), height(x->right)) + 1;
y->height = max(height(y->left), height(y->right)) + 1;
return y;
}
// Get Balance factor of node N
int getBalance(Node *N)
{
if (N == NULL)
return 0;
return height(N->left) - height(N->right);
}
Node *insertnewNode(Node *node, std::string key)
{
if (node == NULL)
return (newNode(key));
if (key < node->key)
node->left = insertnewNode(node->left, key);
else if (key > node->key)
node->right = insertnewNode(node->right, key);
else
return node;
node->height = 1 + max(height(node->left),
height(node->right));
int balance = getBalance(node);
if (balance > 1 && key < node->left->key)
return rightRotation(node);
if (balance < -1 && key > node->right->key)
return leftRotation(node);
if (balance > 1 && key > node->left->key)
{
node->left = leftRotation(node->left);
return rightRotation(node);
}
if (balance < -1 && key < node->right->key)
{
node->right = rightRotation(node->right);
return leftRotation(node);
}
return node;
}
void Inorder(Node *root)
{
if (root == NULL)
return;
Inorder(root->left); //visit left sub-tree
std::cout << root->key << std::endl; //visit root(key node)
Inorder(root->right); //visit right sub-tree
}
bool wordCount(const Node &node1, const Node &node2)
{
}
int main(int argc, char *argv[])
{
Node *root = NULL; //pointer to bstNode. Store address of root node.
//set to NULL(empty tree)
std::cout << "Please enter the name of the file: " << std::endl; //prompts user for the filename
std::cin >> argv[0]; //stores the filename is the first element of argv[]
fileName = argv[0];
std::cout << "Attempting to read file " << fileName << std::endl;
readFile.open(fileName); //attempts to read the file
if (!readFile)
{
std::cerr << "ERROR: failed to open file " << std::endl; //if the file cannot be opened an error is displayed
exit(0); //if it cannot open the console terminates
}
else
{
std::cerr << "File successfully opened" << std::endl;
}
while (readFile >> storeFile)
{
std::transform(storeFile.begin(), storeFile.end(), storeFile.begin(), ::tolower);
for (int i = 0, len = storeFile.size(); i < len; i++)
{
// check whether parsing character is punctuation or not
if (ispunct(storeFile[i]))
{
storeFile.erase(std::remove_if(storeFile.begin(), storeFile.end(), ::isspace), storeFile.end());
storeFile.erase(std::remove_if(storeFile.begin(), storeFile.end(), ::ispunct), storeFile.end());
}
}
root = insertnewNode(root, storeFile);
}
Inorder(root);
readFile.close();
return 0;
}
The implementation im currently struggling with is the count of each word. So for exmaple below, the word is on the left and the count is on the right
adams: 2
apple: 5
as: 20
I attempted a function called bool countWords which the paramaters I believe would be needed(in this case two nodes to compare and match a case). However im not to sure myself how to implemenent it
Thankyou
Just because this hasn't been answered yet, here's the idea behind the solution which I've proposed. You have already converted the input from the file to lowercase, so we can assume that all of the strings are the same case:
typedef std::map<std::string, uint32_t> omap;
omap occurrences;
void printNumOccur( const omap& m )
{
for ( omap::it = m.begin(); it != m.end(); ++it )
{
std::cout << it->first << ": " << it->second << std::endl;
}
}
Node *insertnewNode(Node *node, std::string key)
{
if (node == NULL)
return (newNode(key));
omap::iterator it;
if ( (it = occurrences.find(key)) != m.end() )
it->second++;
else
occurrences.insert({key, 1});
if (key < node->key)
node->left = insertnewNode(node->left, key);
else if (key > node->key)
node->right = insertnewNode(node->right, key);
else
return node;
node->height = 1 + max(height(node->left),
height(node->right));
int balance = getBalance(node);
if (balance > 1 && key < node->left->key)
return rightRotation(node);
if (balance < -1 && key > node->right->key)
return leftRotation(node);
if (balance > 1 && key > node->left->key)
{
node->left = leftRotation(node->left);
return rightRotation(node);
}
if (balance < -1 && key < node->right->key)
{
node->right = rightRotation(node->right);
return leftRotation(node);
}
return node;
}
It seems like the easiest approach would be to maintain the count of each string in the node and increment it every time a matching node is found.
struct Node
{
std::string key;
int height;
Node *left;
Node *right;
int count;
};
Node* newNode(std::string const& key)
{
Node *node = new Node();
node->key = key;
node->left = NULL;
node->right = NULL;
node->height = 1;
node->count = 1;
return node;
}
if (key < node->key)
node->left = insertnewNode(node->left, key);
else if (key > node->key)
node->right = insertnewNode(node->right, key);
else
{
node->count++;
return node;
}
Once the tree is assembled you will need to iterate all nodes. There are two ways you could do this:
Whenever creating a new node, add a pointer to it in a vector
Write a "TreeBrowser" class to scan the tree and dump the outputs. If you want the output to be in order, you will need to walk up and down the tree, remembering what level each branch started from.
Related
Consider the following AVL-tree implementation. Each node contains a list of numbers.The key is named workload, but consider it as a plain double variable. If a key is equal to the key of an already existing node, the number gets pushed into the list. Every time I pop a number from a list, I perform a check, if the node's list is empty -> remove the node. But, after the element with key=3 gets removed completely, the list of the node with key=4 is suddenly empty. I've been trying to solve it for over 10 hours now, it's actually the first time I ever needed to ask something here. Pardon me if I miss a few things.
#include<iostream>
#include <list>
using namespace std;
class BST
{
struct node
{
double workload;
list<int> numbers;
node* left;
node* right;
int height;
};
node* root;
unsigned long long size;
bool empty;
void makeEmpty(node* t)
{
if(t == NULL)
return;
makeEmpty(t->left);
makeEmpty(t->right);
delete t;
}
node* insert(double workload,int number, node* t)
{
if(t == NULL)
{
t = new node;
t->workload = workload;
t->numbers.push_back(number);
t->height = 0;
t->left = t->right = NULL;
}
else if(t->workload == workload){
t->numbers.push_back(number);
}
else if(workload < t->workload)
{
t->left = insert(workload, number, t->left);
if(height(t->left) - height(t->right) == 2)
{
if(workload < t->left->workload)
t = singleRightRotate(t);
else
t = doubleRightRotate(t);
}
}
else if(workload > t->workload)
{
t->right = insert(workload, number, t->right);
if(height(t->right) - height(t->left) == 2)
{
if(workload > t->right->workload)
t = singleLeftRotate(t);
else
t = doubleLeftRotate(t);
}
}
//if x == t->workload instead of using int workload. its a list and we push into it.
t->height = max(height(t->left), height(t->right))+1;
return t;
}
node* singleRightRotate(node* &t)
{
node* u = t->left;
t->left = u->right;
u->right = t;
t->height = max(height(t->left), height(t->right))+1;
u->height = max(height(u->left), t->height)+1;
return u;
}
node* singleLeftRotate(node* &t)
{
node* u = t->right;
t->right = u->left;
u->left = t;
t->height = max(height(t->left), height(t->right))+1;
u->height = max(height(t->right), t->height)+1 ;
return u;
}
node* doubleLeftRotate(node* &t)
{
t->right = singleRightRotate(t->right);
return singleLeftRotate(t);
}
node* doubleRightRotate(node* &t)
{
t->left = singleLeftRotate(t->left);
return singleRightRotate(t);
}
node* findMin(node* t)
{
if(t == NULL)
return NULL;
else if(t->left == NULL)
return t;
else
return findMin(t->left);
}
node* findMax(node* t)
{
if(t == NULL)
return NULL;
else if(t->right == NULL)
return t;
else
return findMax(t->right);
}
node* find(node* t,double workload){
if (t->workload == workload){
return t;
}
else if(workload < t->workload && t->left!=NULL)
return find(t->left,workload);
else if(workload > t->workload && t->right!=NULL)
return find(t->right,workload);
else{
cout << "Null node encountered" << endl;
return t;
}
}
node* remove(double x, node* t)
{
node* temp;
// Element not found
if(t == NULL)
return NULL;
// Searching for element
if(x < t->workload)
t->left = remove(x, t->left);
else if(x > t->workload)
t->right = remove(x, t->right);
// Element found
// With 2 children
else if(t->left && t->right)
{
temp = findMin(t->right);
t->workload = temp->workload;
t->right = remove(t->workload, t->right);
}
// With one or zero child
else
{
temp = t;
if(t->left == NULL)
t = t->right;
else if(t->right == NULL)
t = t->left;
delete temp;
}
if(t == NULL)
return t;
t->height = max(height(t->left), height(t->right))+1;
// If node is unbalanced
// If left node is deleted, right case
if(height(t->left) - height(t->right) == -2)
{
// right right case
if(height(t->right->right) - height(t->right->left) == 1)
return singleLeftRotate(t);
// right left case
else
return doubleLeftRotate(t);
}
// If right node is deleted, left case
else if(height(t->right) - height(t->left) == 2)
{
// left left case
if(height(t->left->left) - height(t->left->right) == 1){
return singleRightRotate(t);
}
// left right case
else
return doubleRightRotate(t);
}
return t;
}
int height(node* t)
{
return (t == NULL ? -1 : t->height);
}
int getBalance(node* t)
{
if(t == NULL)
return 0;
else
return height(t->left) - height(t->right);
}
void inorder(node* t)
{
if(t == NULL)
return;
inorder(t->left);
cout << t->workload<< " ";
inorder(t->right);
}
//Reverse inorder (Sorted highest to lowest)
void rinorder(node* t)
{
if(t == NULL)
return;
rinorder(t->right);
cout << t->workload << " ";
rinorder(t->left);
}
void preorder(node* t)
{
if (t == NULL)
return;
cout << t->workload << " ";
preorder(t->left);
preorder(t->right);
}
void postorder(node* t)
{
if (t == NULL)
return;
postorder(t->left);
postorder(t->right);
cout << t->workload << " ";
}
public:
BST()
{
root = NULL;
}
void insert(double workload, int number)
{
root = insert(workload, number, root);
}
void remove(double workload)
{
root = remove(workload, root);
}
void displayrin()
{
cout << "Rinorder: ";
rinorder(root);
cout << endl;
}
void displayin()
{
cout << "Inorder: ";
inorder(root);
cout << endl;
}
void displaypost()
{
cout << "Postorder: ";
postorder(root);
cout << endl;
}
void displaypre()
{
cout << "Preorder: ";
preorder(root);
cout << endl;
}
double getMax(){
return findMax(root)->workload;
}
int getMaxNum(){
return find(root,getMax())->numbers.front();
}
int getNum(double workload){
return find(root,workload)->numbers.front();
}
//We pop a Num from a node
void popnumber(double workload){
node *t = find(root,workload);
if(t!=NULL){
if(!t->numbers.empty()){
t->numbers.pop_front();
//If the Num list of the node is empty, remove node
if(t->numbers.empty()){
remove(t->workload);
}
}
}
}
};
int main()
{
BST t;
//key value pairs
t.insert(2,1);
t.insert(3,1);
t.insert(3,2);
t.insert(4,7);
cout << t.getNum(4) << endl;
cout << t.getNum(3)<<endl;
t.popnumber(3);
cout << t.getNum(3)<<endl;
t.popnumber(3);
t.displayin();
t.displaypost();
t.displaypre();
t.displayrin();
cout << t.getNum(4) << endl;
cout << "The max is : " << t.getMax() << endl;
cout << "The top Num of the Max is : " << t.getMaxNum() << endl;
return 0;
}
As mentioned in the comments, the problem is in the "Element found With 2 children" section of remove.
To remove the element, you find the next element in the tree. Your implementation then wants to copy the contents of the found node (temp). You copy the workload value, so that both t and temp have the same workload value (4). You do not copy the numbers list. The t node has a workload of 4 and an empty numbers list, while temp has a workload of 4 and a numbers list consisting of one element, 7. You then delete temp, losing the list.
One fix would be to copy (or move) numbers from temp to t before removing it from the tree. Adding a MoveData method to node that would move the data fields (while not altering the tree specific fields) would make it easier to add new data fields.
Another fix would be to change how you're doing the data update. If you update all pointers (and other tree related fields like height), then you don't have to worry about the data (and any pointers/iterators to the nodes would not be invalidated).
I am trying to insert 0 through 11 into avl and then delete 4, 5, 6 in that order. I am getting sigserv error while deleting 6 in rr_rotation function. This is the first time I am implementing avl and I am new to programming. Where am I going wrong? I added a few comments for my own understanding and to track where the error has occurred. Here is my code:
#include<bits/stdc++.h>
using namespace std;
#define pow2(n) (1 << (n))
struct avl_node {
int data;
//int size;
struct avl_node *left;
struct avl_node *right;
}*root;
class avlTree {
public:
int height(avl_node *);
int diff(avl_node *);
avl_node *rr_rotation(avl_node *);
avl_node *ll_rotation(avl_node *);
avl_node *lr_rotation(avl_node *);
avl_node *rl_rotation(avl_node *);
avl_node* balance(avl_node *);
avl_node* insert(avl_node *, int);
int getBalance(avl_node*);
int getSize(avl_node*);
avl_node* minValueNode(avl_node*);
avl_node* del(avl_node *, int);
void inorder(avl_node *);
void preorder(avl_node *);
int kthsmallest(avl_node*, int);
avlTree() {
root = NULL;
}
};
int avlTree::height(avl_node *temp) {
int h = 0;
if (temp != NULL) {
int l_height = height(temp->left);
int r_height = height(temp->right);
int max_height = max(l_height, r_height);
h = max_height + 1;
}
return h;
}
int avlTree::diff(avl_node *temp) {
int l_height = height(temp->left);
int r_height = height(temp->right);
int b_factor = l_height - r_height;
return b_factor;
}
avl_node *avlTree::rr_rotation(avl_node *parent) {
avl_node *temp;
cout<<"inside rr rotation"<<endl;
cout<<"parent = "<<parent->data<<endl;
temp = parent->right;
if(temp == NULL)
cout<<"yes null 2"<<endl;
//cout<<"parent->right "<<temp->data<<endl;
parent->right = temp->left;
temp->left = parent;
cout<<"temp->left->data "<<temp->left->data<<endl;
return temp;
}
avl_node *avlTree::ll_rotation(avl_node *parent) {
avl_node *temp;
//cout<<"inside ll rotation"<<endl;
//cout<<"parent = "<<parent->data<<endl;
temp = parent->left;
parent->left = temp->right;
temp->right = parent;
return temp;
}
avl_node *avlTree::lr_rotation(avl_node *parent) {
avl_node *temp;
cout<<"inside lr rotation"<<endl;
cout<<"parent = "<<parent->data<<endl;
temp = parent->left;
parent->left = rr_rotation(temp);
return ll_rotation(parent);
}
avl_node *avlTree::rl_rotation(avl_node *parent) {
avl_node *temp;
cout<<"inside rl rotation"<<endl;
cout<<"parent = "<<parent->data<<endl;
temp = parent->right;
parent->right = ll_rotation(temp);
return rr_rotation(parent);
}
avl_node *avlTree::balance(avl_node *temp) {
int bal_factor = diff(temp);
if (bal_factor > 1) {
if (diff(temp->left) > 0)
temp = ll_rotation(temp);
else
temp = lr_rotation(temp);
} else if (bal_factor < -1) {
if (diff(temp->right) > 0)
temp = rl_rotation(temp);
else
temp = rr_rotation(temp);
}
return temp;
}
avl_node *avlTree::insert(avl_node *root, int value) {
//cout<<"Inside insert for val = "<<value<<endl;
if (root == NULL) {
root = new avl_node;
root->data = value;
root->left = NULL;
root->right = NULL;
return root;
} else if (value < root->data) {
root->left = insert(root->left, value);
root = balance(root);
} else if (value >= root->data) {
root->right = insert(root->right, value);
root = balance(root);
}
return root;
}
avl_node* avlTree::minValueNode(avl_node* node) {
avl_node* current = node;
while (current->left != NULL)
current = current->left;
return current;
}
int avlTree::getBalance(avl_node* N) {
if (N == NULL)
return 0;
return height(N->left) - height(N->right);
}
avl_node* avlTree::del(avl_node *root, int value) {
cout<<"del for val = "<<value<<endl;
if (root == NULL){
cout<<"root is null here\n";
return root;
}
// If the key to be deleted is smaller than the
// root's key, then it lies in left subtree
if (value < root->data)
root->left = del(root->left, value);
// If the key to be deleted is greater than the
// root's key, then it lies in right subtree
else if (value > root->data)
root->right = del(root->right, value);
// if key is same as root's key, then This is
// the node to be deleted
else {
// node with only one child or no child
if ((root->left == NULL) || (root->right == NULL)) {
avl_node* temp = root->left ? root->left : root->right;
// No child case
if (temp == NULL) {
temp = root;
root = NULL;
cout<<"Root set to null\n";
}
else{
// One child case
cout<<temp->data<<" copied to root "<<root->data<<"\n";
*root = *temp;
// Copy the contents of
// the non-empty child
}
free(temp);
} else {
// node with two children: Get the inorder
// successor (smallest in the right subtree)
avl_node* temp = minValueNode(root->right);
// Copy the inorder successor's data to this node
root->data = temp->data;
// Delete the inorder successor
root->right = del(root->right, temp->data);
}
} // If the tree had only one node then return
if (root == NULL)
return root;
// STEP 2: UPDATE HEIGHT OF THE CURRENT NODE
//root->height = 1 + max(height(root->left),height(root->right));
// STEP 3: GET THE BALANCE FACTOR OF THIS NODE (to
// check whether this node became unbalanced)
int balance = getBalance(root);
cout<<"balance = "<<balance<<" for root "<<root->data<<endl;
if(root->right == NULL)
cout<<"yes null"<<endl;
// If this node becomes unbalanced, then there are 4 cases// Left Left Case
if (balance > 1 && getBalance(root->left) >= 0){
cout<<"balance1 = "<<getBalance(root->left)<<" for root "<<root->left->data<<endl;
avl_node* t = rr_rotation(root);
//root = rr_rotation(root);
cout<<"Root of the modified sub-tree is "<<t->data<<endl;
return t;
//rr_rotation(root);
}
// Left Right Case
if (balance > 1 && getBalance(root->left) < 0) {
cout<<"balance2 = "<<getBalance(root->left)<<" for root "<<root->left->data<<endl;
cout<<"prev root "<<root->left->data<<endl;
//root->left = ll_rotation(root->left);
root = lr_rotation(root);
cout<<"new root "<<root->data<<endl;
//return rr_rotation(root);
return root;
} // Right Right Case
if (balance < -1 && getBalance(root->right) <= 0){
cout<<"balance3 = "<<getBalance(root->right)<<" for root "<<root->right->data<<endl;
avl_node* t = rr_rotation(root);
cout<<"Root of the modified sub-tree is "<<t->data<<endl;
return t;
//return ll_rotation(root);
}
// Right Left Case
if (balance < -1 && getBalance(root->right) > 0) {
cout<<"balance4 = "<<getBalance(root->right)<<" for root "<<root->right->data<<endl;
//root->right = rr_rotation(root->right);
//return ll_rotation(root);
return rl_rotation(root);
}
return root;
}
void avlTree::inorder(avl_node *tree) {
if (tree == NULL)
return;
inorder(tree->left);
cout << tree->data << " ";
inorder(tree->right);
}
void avlTree::preorder(avl_node *tree) {
if (tree == NULL)
return;
cout << tree->data << " ";
preorder(tree->left);
preorder(tree->right);
}
int avlTree::getSize(avl_node* N){
if(N == NULL)
return 0;
return (getSize(N->left) + 1 + getSize(N->right));
}
int avlTree::kthsmallest(avl_node* N, int k){
int r = getSize(N->left) + 1;
if(k == r)
return N->data;
if(k < r)
return kthsmallest(N->left,k);
if(k > r)
return kthsmallest(N->right,k-r);
return -1;
}
int main(void) {
int n, i, x;
char s;
avlTree tree; for(i=0;i<12;i++){
root = tree.insert(root,i);
tree.preorder(root);
cout<<endl;
}
for(i=4;i<=6;i++){
root = tree.del(root,6);
tree.preorder(root);
cout<<endl;
}
return 0;
}
I 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();
}
}
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.
Why the search and successor and predecessor returns -1?
// BST.cpp : main project file.
#include "stdafx.h"
#include <cstdlib>
#include <iostream>
#define SIZE 10
using namespace std;
struct Node {
int value;
Node *left;
Node *right;
Node *parent;
};
struct BST {
Node *root;
};
void insert(int value, BST *tree) {
Node *x = tree->root;
Node *y = NULL;
Node *z = (Node *) malloc(sizeof(Node));
z->left = NULL;
z->right = NULL;
z->value = value;
// Add your code here
while (x!=NULL){
y=x;
if (z->value < x->value)
x= x->left;
else x = x->right;
}
z->parent=y;
if (y==NULL)
tree->root=z;
else if (z->value <y->value)
y->left =z;
else y->right =z;
}
Node *search(int key, Node *n) {
if (n== NULL || key == n->value)
return n;
if (key < n->value)
search(key, n->left);
else
search(key, n->right);
}
Node *min(Node *n) {
if (n == NULL || n->left == NULL)
return n;
else
return min(n->left);
}
Node *max(Node *n) {
if (n == NULL || n->right == NULL)
return n;
else
return max(n->right);
}
Node *successor(int value, Node *n) {
Node *y = NULL;
Node *x = search(value, n);
if (x == NULL)
return NULL;
if (x->right != NULL)
return min(x->right);
y = x->parent;
while (y != NULL && x == y->right) {
x = y;
y = y->parent;
}
return y;
}
Node *predecessor(int value, Node *n) {
Node *x = search(value, n);
Node *y = NULL;
if (x == NULL)
return NULL;
if (x->left != NULL)
return max(x->left);
y = x->parent;
while (y != NULL && x == y->left) {
x = y;
y = y->parent;
}
return y;
}
Node *remove(int value, BST *tree) {
Node *z = search(value, tree->root);
Node *y = NULL, *x = NULL;
if (z == NULL) return NULL;
if (z->left == NULL || z->right == NULL)
y = z;
else
y = successor(value, z);
if (y->left != NULL)
x = y->left;
else
x = y->right;
if (x != NULL)
x->parent = y->parent;
if (y->parent == NULL)
tree->root = x;
else if (y == y->parent->left)
y->parent->left = x;
else
y->parent->right = x;
if (y != z) {
int tmp = z->value;
z->value = y->value;
y->value = tmp;
}
return y;
}
// ascending sort function
void sortAsc(Node *node) {
//Add your code here
//inorder
if (node->left!=NULL)
sortAsc(node->left);
cout<<node->value<<" ";
if (node->right!=NULL)
sortAsc(node->right);
}
// descending sort function
void sortDes(Node *node) {
// Add your code here
//inorder
if (node->right!=NULL)
sortDes(node->right);
cout<<node->value<<" ";
if (node->left!=NULL)
sortDes(node->left);
}
void clear(BST *tree) {
Node *n = NULL;
while (tree->root != NULL) {
n = remove(tree->root->value, tree);
free(n);
}
}
int main() {
int A[] = {3, 5, 10, 4, 8, 9, 1, 4, 7, 6};
Node *node = NULL;
BST *tree = (BST *) malloc(sizeof(BST));
tree->root = NULL;
// build BST tree
cout << "Input data:\n\t";
for (int i=0; i<SIZE; i++) {
cout << A[i] << " "; // by the way, print it to the console
insert(A[i], tree); // You need to complete TASK 1, so that it can work
}
// sort values in ascending order
cout << "\n\nAscending order:\n\t";
sortAsc(tree->root); // You need to complete TASK 2. Otherwise you see nothing in the console
// sort values in descending order
cout << "\n\nDescending order:\n\t";
sortDes(tree->root); // TASK 2 also!
// Find minimum value
if (tree->root != NULL)
cout << "\n\nMin: " << min(tree->root)->value;
// Find maximum value
if (tree->root != NULL)
cout << "\n\nMax: " << max(tree->root)->value;
// delete 4
cout << "\n\nDelete 4 and add 2";
//free(remove(4, tree)); // You need to complete TASK 3, so that remove(int, BST *) function works properly
// we also need to release the resource!!!
// insert 2
insert(2, tree); // It belongs to TASK 1 too.
cout << "\n\nAscending order:\n\t";
sortAsc(tree->root); // TASK 2!!
// Find the successor of 5, -1 means no successor
node = search(5, tree->root);
cout << "\n\nSearch of 5 is: " << (node != NULL?node->value:-1);
// Find the successor of 5, -1 means no successor
node = successor(5, tree->root);
cout << "\n\nSuccessor of 5 is: " << (node != NULL?node->value:-1);
// Find the predecessor of 5. -1 means no predecessor
node = predecessor(5, tree->root);
cout << "\n\nPredecessor of 5 is: " << (node != NULL?node->value:-1);
cout << "\n\n";
// clear all elements
clear(tree); // delete all nodes and release resource
free(tree); // delte the tree too
system("Pause");
}
Well there is a bug in your recursive search for starters you need to have all paths return values like this:
Node *search(int key, Node *n) {
if (n== NULL || key == n->value)
return n;
if (key < n->value)
return search(key, n->left);
else
return search(key, n->right);
}
Apart from that I'm inclined to say try debugging your own code first and giving more details about what you've found rather than just posting code and asking what's wrong with it. You're liable to get some real smart ass answers here otherwise ;)