AVL Tree strange behavior - c++

The following code got me really puzzled.
class
class AVLTree {
private:
struct AVLNode
{
AVLNode *leftchild;
AVLNode *rightchild;
int data;
int height;
};
AVLNode *root;
public:
AVLTree()
{
root = NULL;
}
bool isEmpty() const { return root == NULL; }
void print();
void inorder(AVLNode *n, int l);
void insert(int d);
void rotateLeft(AVLNode* n);
void rotateRight(AVLNode* n);
void rotateLeftTwice(AVLNode* n);
void rotateRightTwice(AVLNode* n);
AVLTree::AVLNode* insert(int d, AVLNode* n);
int max( int a, int b);
int height( AVLNode* n); };
insert function.
AVLTree::AVLNode* AVLTree::insert(int d,AVLNode *n){
if (n == NULL)
{
AVLNode *n = new AVLNode;
n->data = d;
n->leftchild = NULL;
n->rightchild = NULL;
n->height = 0;
} else if( d < n->data) {
n->leftchild = insert(d,n->leftchild);
} else if (d > n->data) {
n->rightchild = insert(d,n->rightchild);
}
else {
n->height = max(height(n->leftchild), height(n->rightchild));
return n;
}
-----> This section of the code gives be "EXC_BAD_ACCESS".
n->height = max(height(n->leftchild), height(n->rightchild));
return n;
}
This is the height function.
int AVLTree::height(AVLNode* node)
{ cout << "HEIGHT";
if(node == NULL)
{
return -1;
}
else {
return node->height;
}
}
Anyone knows why?
=== Update:
when doing the rotation
void AVLTree::rotateLeft(AVLNode* n)
{
AVLNode *child = n->leftchild;
n->leftchild = child->rightchild;
child->rightchild = n;
n->height = max(height(n->leftchild),height(n->rightchild))+1;
child->height = max(height(child->leftchild),height(child->rightchild))+1;
n = child;
}
It seems not to be swapping values as it should. While n = child seems to swap locally it does not reflect a change i the rest of the code. Giving me an infinite loop.

If n was null on entry to the function, then that line will attempt to dereference it, giving the error. Your code to allocate a new node should assign it to n itself, rather than a separate variable with the same name that shadows the function argument.
Change the first line of the if (n == NULL) block from
AVLNode *n = new AVLNode;
to
n = new AVLNode;
Regarding the update: In your rotate function, n is a local (automatic) variable, and changing that won't affect anything outside the function. You will need to either pass the pointer by reference, or return the new pointer value (like you do in insert()).

Related

Binary Search Tree Deletion Problem When creating the Node class with left node first

I am creating a binary search tree in C++ using classes. When I write the left address first as in the example, deletion is not working correctly for random nodes.
Example:
class Node{
public:
int data;
Node* left;
Node* right;
Node(){ data=0; right=left=NULL;};
Node(int x){ data=x; right=left=NULL;};
bool is_leaf(){ return (left==NULL && right==NULL);
}
};
class BST{
private:
Node* root;
Node * _del(int x,Node* n);
void _insert_rec(int x,Node*n);
public:
BST(){ root=NULL; };
void insert_rec(int x);
void print();
void del(int x);
};
void BST::del(int x)
{
root = _del(x,root);
}
Node * BST::_del(int x,Node* n)
{
if(!n)
return NULL;
else
{
if(x<n->data)
n->left = _del(x,n->left);
else if(x>n->data)
n->right = _del(x,n->right);
else
{
if(n->is_leaf())
{
delete n;
return NULL;
}
else
{
if(!n->right)
{
delete n;
return n->left;
}
else if (!n->left)
{
delete n;
return n->right;
}
else
{
int enb = _max_value(n->left);
n->data = enb;
n->left = _del(enb,n->left);
}
}
}
}
return n;
}
void BST::insert_rec(int x)
{
root = _insert_rec(x,root);
}
Node * BST::_insert_rec(int x,Node* r)
{
if(!r)
return new Node(x);
else
{
if(x>r->data)
r->right = _insert_rec(x,r->right);
else
r->left = _insert_rec(x,r->left);
}
return r;
}
int main(int argc, char** argv)
{
BST *bst = new BST();
bst->insert_rec(50);
bst->insert_rec(100);
bst->insert_rec(20);
bst->insert_rec(10);
bst->insert_rec(70);
bst->print();
bst->del(100);
cout<<endl;
bst->print();
return 0;
}
When I try to delete 100 or 50, the code doesn't work.
If I change the Node class as below everything works fine:
class Node{
public:
int data;
Node* right; // Only changed the order of the addresses.
Node* left;
Node(){ data=0; right=left=NULL;};
Node(int x){ data=x; right=left=NULL;};
bool is_leaf(){ return (left==NULL && right==NULL);
}
};
Changed the order of the addresses. But I want to understand the reason behind this situation.
One problem is here
if(!n->right)
{
delete n;
return n->left;
}
You are deleting the pointer n and then dereferencing it. You should use a temporary variable
if(!n->right)
{
Node* tmp = n->left;
delete n;
return tmp;
}
With that change (in two places) it seems to work for me.

Circular Single Linked List C++ Delete Problem

I want to remove one node from a Circular Single Linked List and when i reach to the Cmd, it shows me an address (maybe) which is repeating infintely. Please help me or show me what is wrong. Here is the code in C++
using namespace std;
class Node{
private:
int data;
Node * next;
public:
void setdata(int s);
int getdata()
{
return data;
}
void setnext(Node * next_pointer);
Node * getnext();
};
void Node::setdata(int s){
data = s;
}
Node * Node::getnext(){
return this->next;
}
void Node::setnext(Node *next_node)
{
this->next = next_node;
}
class Circular{
private:
Node * first;
int sizen;
public:
Circular();
void append(int value);
void display();
Node * walk(int start, int die=3);
int remove_node(Node * prev_node);
int getsize();
Node * get_first();
void removing(int val);
};
Circular::Circular(){
first = 0;
sizen = 0;
}
void Circular::append(int val)
{
Node * new_node = new Node;
new_node -> setdata(val);
if(this->sizen == 0 )
{
//There is empty
this->first = new_node;
this->first -> setnext(this->first);
this->sizen = 1;
}
else
{
//It's not empty
Node *node = this->first;
while(node->getnext()!= this->first)
{
node = node->getnext();
}
node->setnext(new_node);
node->getnext() -> setnext(this->first);
this->sizen +=1;
}
}
void Circular::display()
{
Node *temp = this->first;
std::cout<<temp->getdata()<<" ";
temp = temp->getnext();
while(temp!=this->first)
{
std::cout<<temp->getdata()<<" ";
temp = temp->getnext();
}
}
void Circular::removing(int val)
{
Node *new_node = this->first, *d;
/*if(new_node->sizen==0)
return 0;
if(new_node->sizen==1 && new_node->getdata() == val)
{free(new_node);
return 0;
}*/
std::cout<<"Removing "<<val<<std::endl;
while((new_node->getnext())->getdata()!=val)
{
new_node = new_node->getnext();
}
if((new_node->getnext())->getdata()==val)
{
d = new_node->getnext();
new_node->getnext() ->setnext(d->getnext());
free(d);
}
}
int Circular::getsize(){
Node *temp = this->first;
int length = 0;
length++;
while(temp->getnext()!=this->first)
{
temp = temp->getnext();
length++;
}
return length;
}
int main(){
Circular l;
int i, n,k;
std::cout<<"How many participants do you want? ";
std::cin>>n;
std::cout<<"Which participant should be killed? (Kth)";
std:cin>>k;
for(i=1;i<=n;i++)
l.append(i);
l.display();
l.removing(2);
l.display();
}
And Here is where the problem gets me anxious:
void Circular::removing(int val)
{
Node *new_node = this->first, *d;
/*if(new_node->sizen==0)
return 0;
if(new_node->sizen==1 && new_node->getdata() == val)
{free(new_node);
return 0;
}*/
std::cout<<"Removing "<<val<<std::endl;
while((new_node->getnext())->getdata()!=val)
{
new_node = new_node->getnext();
}
if((new_node->getnext())->getdata()==val)
{
d = new_node->getnext();
new_node->getnext() ->setnext(d->getnext());
free(d);
}
}
I have no error and when I run the program, I want to remove the Second (2) node, but it shows me:
1 1114304 1114304 1114304 1114304 1114304 and so on.

A count function that counts the leaf nodes of a height balanced tree

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

SIGSEGV error with BFS Algorithm

I have a BFS algorithm error.
Have tried to debug with the gdb but I don't understand why I get this.
Can anyone tell me why i get a SIGSEGV error with the code below. Does it depend on the compiler that you use how the pointers are addressed? As there is an invalid pointer error in the code
#include<iostream>
#include<stdlib.h>
#define TRUE 1
#define FALSE 0
using namespace std;
const int MAX = 8;
struct Node
{
int data;
Node *next;
};
class Graph
{
private:
int visited[MAX];
int q[8];
int front, rear;
public:
Graph();
void BFS(int v, Node **p);
Node *getNode_Write(int val);
static void addQueue(int *a, int vertex, int *f, int *r);
static int deleteQueue(int *q, int *f, int *r);
static int isEmpty(int *f);
void del(Node *n);
};
// initialize data memeber
Graph::Graph()
{
for(int i = 0; i < MAX; i++)
visited[i] = FALSE;
front = rear = -1;
}
// function that implements breadth first search (BFS) algorithm
void Graph::BFS(int v, Node **p)
{
Node *u;
visited[v-1] = TRUE;
cout<<v<<"\t";
addQueue(q, v, &front, &rear);
while(isEmpty(&front) == FALSE)
{
v = deleteQueue(q, &front, &rear);
u = *(p+v-1);
while(u != NULL)
{
if(visited[u->data-1] == FALSE)
{
addQueue(q, u->data, &front, & rear);
visited[u->data-1] == TRUE;
cout<<u->data<<"\t";
}
u = u->next;
}
}
}
// Creates a node
Node *Graph::getNode_Write(int val)
{
Node *newNode = new Node;
newNode->data = val;
return newNode;
}
//Adds node to the queue
void Graph::addQueue(int *a, int vertex, int *f, int *r)
{
if(*r == MAX -1)
{
cout<<"\nQueue Overflow.";
exit(0);
}
(*r)++;
a[*r] = vertex;
if(*f == -1)
*r = 0;
}
// Deletes a node from the queue
int Graph::deleteQueue(int *a, int *f, int *r)
{
int data;
if(*f == -1)
{
cout<<"\nQueue Underflow";
exit(0);
}
data = a[*f];
if(*f == *r)
*f = *r = -1;
else
(*f)++;
return data;
}
// checks if queque is empty
int Graph::isEmpty(int *f)
{
if(*f == -1)
return TRUE;
return FALSE;
}
// deallocate the memory
void Graph::del(Node *n)
{
Node *temp;
while(n != NULL)
{
temp = n->next;
delete n;
n = temp;
}
}
int main()
{
Node *arr[MAX];
Node *v1,*v2,*v3,*v4;
Graph g;
v1 = g.getNode_Write(2);
arr[0] = v1;
v1->next = v2 = g.getNode_Write(3);
v2->next = NULL;
v1 = g.getNode_Write(1);
arr[1] = v1;
v1->next = v2 = g.getNode_Write(4);
v2->next = v3 = g.getNode_Write(5);
v3->next = NULL;
cout<<endl;
g.BFS(1,arr);
for(int i = 0; i<MAX; i++)
g.del(arr[i]);
}
There is an uninitialized array arr in the stack frame of main. Only arr[0] and arr[1] become initialized. At the end of main it is iterated over the whole array and delete is called in Graph::del(Node *n) on a garbage value.
"Does it depend on the compiler that you use how the pointers are addressed?"
No, it doesn't depend on the compiler primarily. As Joachim pointed out in his comment:
To see the real source of the error, you should just step up the stack trace, and check out how all the variables and parameters were actually set.
Most likely you've been calling some undefined behavior, due to missing, or wrong variable initializations.

Binary tree pointer to the root needs to be referenced and dereferenced. Why?

My question is why do I need to dereference and reference a pointer for the following code to work? Doesn't ref/deref cancel each other?
I would really appreciate if anyone could explain it like I'm five :)
Code:
template <typename T>
class binNode {
private:
T key;
public:
binNode * left;
binNode * right;
binNode * parent;
binNode() {
this->left = NULL;
this->right = NULL;
this->parent = NULL;
}
// arg constructor:
binNode (T key) {
this->key = key;
this->left = NULL;
this->right = NULL;
this->parent = NULL;
}
T getKey() {
return this->key;
}
void setKey(T key) {
this->key = key;
}
};
template<typename T> class Tree {
private:
binNode <T> *root;
public:
Tree() {
this->root = NULL;
}
Tree(binNode <T> * node) {
node->parent = NULL;
this->root = node;
}
/* THIS IS THE PART I DON'T GET */
void addNode(binNode<T> *&x, binNode<T> * node) { // what's up with the *&???
if (x == NULL) {
x = node;
return;
} else if (x->getKey() == node->getKey()) {
node->left = x;
node->parent = x->parent;
x->parent = node;
return;
}
if (node->getKey() < x->getKey()) {
addNode(x->left, node);
} else {
addNode(x->right, node);
}
}
void addNode(binNode<T> * node) {
addNode(this->root, node);
}
binNode<T> * treeSearch(binNode<T> * x, T key) {
if (x == NULL || key == x->getKey()) {
return x;
}
if (key < x->getKey()) {
return treeSearch(x->left, key);
} else {
return treeSearch(x->right, key);
}
}
void printOrdered() {
inorderTreeWalk(root);
cout << endl;
}
void inorderTreeWalk(binNode<T> * node) {
if (node != NULL) {
inorderTreeWalk(node->left);
cout << node->getKey() << '\t';
inorderTreeWalk(node->right);
}
}
};
Here is the main function (#inlude is not included)
int main() {
Tree<int> T (new binNode<int>(10));
// Tree<int> T = new binNode<int>(10);
T.addNode(new binNode<int> (11));
T.addNode(new binNode<int> (9));
T.addNode(new binNode<int> (8));
T.addNode(new binNode<int> (12));
T.printOrdered();
}
That's not a reference / dereference of a pointer, it's a reference to a pointer. It is necessary because...
void addNode(binNode<T> *&x, binNode<T> * node) {
if (x == NULL) {
x = node; // ...here...
return;
} else // ...
...you are assigning to the parameter x.
If you hadn't passed the pointer x by reference, you would assign to the local copy of the parameter:
void addNode(binNode<T> * x, binNode<T> * node) {
if (x == NULL) {
x = node; // this acts on the local copy only, and thus does nothing.
return;
} else // ...
Via the pointer (without the reference), you get a local copy of the address. Which means you can manipulate the value behind the pointer (in this case *x) which would change. But if you change the address itself, the address would behave like a local copy and you lose the address-changes after leaving the method.