my binary search tree program stopped working (C) - c

For some reason the insertion part of the code is not working as intended. When I run the program it just gives an error "bst.exe has stopped working" and it happens in this function. The whole idea of this portion of the code is to ITERATIVELY insert a new node and update the root.
static NODE *insert_i(NODE *r, int x)
{
NODE *leaf;
if(r == NULL)
{
leaf = malloc(sizeof(NODE));
leaf->left = NULL;
leaf->right = NULL;
leaf->val = x;
count++;
return leaf;
}
while(r)
{
if(r->val == x)
return r;
if(x < r->val && r->left != NULL)
r = r->left;
else if(x > r->val && r->right != NULL)
r = r->right;
}
leaf = malloc(sizeof(NODE));
leaf->left = NULL;
leaf->right = NULL;
leaf->val = x;
count++;
if(x < r->val)
r->left = leaf;
else
r->right = leaf;
return r;
}
void bst_insert(BST_PTR t, int x)
{
t->root = insert_i(t->root, x);
}

At this point, outside the loop
if(x < r->val)
r->left = leaf;
else
r->right = leaf;
r is NULL. So, if you access r->val, it will crash.
Try to keep track of the parent as shown below.
NODE *leaf;
NODE * par
while(r)
{
if(r->val == x)
return r;
par = r;
if(x < r->val && r->left != NULL)
r = r->left;
else if(x > r->val && r->right != NULL)
r = r->right;
}
leaf = malloc(sizeof(NODE));
leaf->left = NULL;
leaf->right = NULL;
leaf->val = x;
count++;
if(x < par->val)
par->left = leaf;
else
par->right = leaf;
return r;

Related

how i can get the height of a red black tree and not the black height

im trying to get the height of a red black tree that inserted in it a file of 3000+ word and it gives me a height = 1968 i dont know if the error in the insertion part or the algorithm of calculating the height
the function for height
#define MAX(a,b) (((a)>(b))?(a):(b))
int height(Node* Root)
{
int h = 0;
if (Root != NULL) {
if (Root == T_Nil)
h = 1;
else
{
int leftHeight = height(Root->left);
int rightHeight = height(Root->right);
h = MAX(leftHeight, rightHeight) + 1;
}
}
return h;
}
Having :
typedef struct Node {
char word[128];
char color;
struct Node * left;
struct Node *right;
struct Node *parent;
} Node;
struct Node T_Nil_Node;
Node * T_Nil = &T_Nil_Node;
insert function
void redBlackInsert(Node** T, char word[128])
{
Node* z = newNode(word);
Node* y = T_Nil;
Node* x = *T;
while (x != T_Nil)
{
y = x;
if (strcmp(z->word,x->word)<0)
x = x->left;
else
x = x->right;
}
z->parent = y;
if (y == T_Nil)
*T = z;
else if (strcmp(z->word,y->word)<0)
y->left = z;
else
y->right = z;
z->left = T_Nil;
z->right = T_Nil;
z->color = RED;
redBlackInsertFixup(T, z);
}
fixup functin
void redBlackInsertFixup(Node** Root, Node* New)
{
Node* temp;
while (New->parent->color == RED)
{
if (New->parent == New->parent->parent->left)
{
temp = New->parent->parent->right;
if (temp->color == RED)
{
New->parent->color = BLACK;
temp->color = BLACK;
New->parent->parent->color = RED;
New = New->parent->parent;
}
else
{
if (New == New->parent->right)
{
New = New->parent;
rotateLeft(Root, New);
}
New->parent->color = BLACK;
New->parent->parent->color = RED;
rotateRight(Root, New->parent->parent);
}
}
else
{
temp = New->parent->parent->left;
if (temp->color == RED)
{
New->parent->color = BLACK;
New->color = BLACK;
New->parent->parent->color = RED;
New = New->parent->parent;
}
else
{
if (New == New->parent->left)
{
New = New->parent;
rotateRight(Root, New);
}
New->parent->color = BLACK;
New->parent->parent->color = RED;
rotateLeft(Root, New->parent->parent);
}
}
}
Root[0]->color = BLACK;
}
rotating left
void rotateLeft( Node** T, Node* x)
{
Node *y = x->right;
x->right = y->left;
if (y->left != T_Nil)
y->left->parent = x;
y->parent = x->parent;
if (x->parent == T_Nil)
*T = y;
else if (x == x->parent->left)
x->parent->left = y;
else
x->parent->right = y;
y->left = x;
x->parent = y;
}
rotating right (i use it in fix up)
void rotateRight(Node** T, Node* y)
{
Node *x = y->left;
y->left = x->right;
if (x->right != T_Nil)
x->right->parent = y;
x->parent = y->parent;
if (y->parent == T_Nil)
*T = x;
else if (y == y->parent->right)
y->parent->right = x;
else
y->parent->left = x;
x->right = y;
y->parent = x;
}
This line looks wrong
if (Root == T_Nil)
h = 1;
I'd expect it to look like this
if (Root->right == NULL && Root->left == NULL)
h = 1;
This is a node that has no children and thus has height of 1.
The function looks like it would work without this if statement since a null value to the function return 0. Since it already has the +1 after the MAX I'm guessing this is the more correct solution.
It seems you are mixing up NULL and a sentinel NIL node in your height function. Either you use NULL for representing "no childern" or you use a sentinel NIL object. Having both at the same time seems wrong.
Besides that it seems wrong to return 1 when a sentinel is reached.
Here is how I would expect the code to be...
Using sentinel NIL (which it seems you want to do)
int height(Node* Root)
{
assert(Root != NULL); // NULL is never allowed
if (Root == T_Nil) return 0; // No data here so return 0
int leftHeight = height(Root->left);
int rightHeight = height(Root->right);
int h = MAX(leftHeight, rightHeight) + 1;
return h;
}
Using NULL (which it seems you don't want to do)
int height(Node* Root)
{
if (Root == NULL) return 0; // No data here so return 0
int leftHeight = height(Root->left);
int rightHeight = height(Root->right);
int h = MAX(leftHeight, rightHeight) + 1;
return h;
}

NULL assignment to a structure pointer is not working through function. What to do?

I am trying to implement BST deletion. According to algorithm, we can delete a leaf directly. Now I'm assigning NULL to leaf directly and still this node remains as it is.
In the test case I gave tried to delete leaf and it is not working.
Please help!
struct node * delet(long data, struct node* root)
{
int i=1;
struct node *temp = root,*t;
while(temp != 0)
{
if(data < temp->data)
{
i=2*i;
temp = temp->l;
}
else if(data > temp->data)
{
i = (2*i)+1;
temp = temp->r ;
}
else
{
printf("%d\n",i);
break;
}
}
if(temp->l == 0 && temp->r == 0)
{
temp = 0;
return root;
}
else if(temp->l == 0)
{
temp->data = temp->l->data;
temp->l = 0;
}
else if(temp->r == 0)
{
temp->data = temp->r->data;
temp->r = 0;
}
else
{
t = temp;
t = t->r;
while(t->l != 0)
{
t = t->l;
}
temp->data = t->data;
if(t->r != 0)
{
t->data = t->r->data;
t->r = 0;
return root;
}
else
{
t = 0;
return root;
}
}
}
temp = 0; doesn't delete the leaf from the tree, just nulls a local variable.
You want to null some node's l or r in order to remove a node from the tree.
Try keeping the parent as well and once temp points to the leaf, nullify temp's parent r or l.
Same goes for t = 0; later on.
Note David's comment about first releasing this memory..
For example (assuming not deleting the root):
...
if(data < temp->data)
{
i=2*i;
parent = temp;
temp = temp->l;
}
else if(data > temp->data)
{
i = (2*i)+1;
parent = temp;
temp = temp->r ;
}
else
{
printf("%d\n",i);
break;
}
...
if(temp->l == 0 && temp->r == 0)
{
if (parent->l == temp)
parent->l = 0;
else
parent->r = 0;
// Free temp if needed
return root;
}
...
Also note that you have:
else if(temp->l == 0)
{
temp->data = temp->l->data;
Which is a dereference of a null pointer (temp->l is NULL), and the same thing for temp->r == 0 case.
Then you have
temp->l = 0;
but you're already in a temp->l == 0 case, so I don't think this is what you meant.

c program red-black-tree insert memory leaks (core dumped) and other issues

I'm working on a red black tree assignment for my class and I'm having some trouble with the insertion function. My problem is that get memory leaks when i try to add more than tree nodes. so i need help with fixing this implementation.
#include <stdio.h>
#include <stdlib.h>
typedef struct Node
{
int key;
char color;
struct Node *left;
struct Node *right;
struct Node *parent;
}Node;
Node *tree = NULL;
Node *createNode(int key) {
Node *temp;
temp = (Node*) malloc(sizeof(Node));
temp->left = NULL;
temp->right = NULL;
temp->key = key;
temp->color = 'R';
return temp;
}
Node* rightRotate(Node *root,Node *x)
{
Node *y;
y = x->right;
x->right = y->left;// zamienia lewe podrzewo y w prawe poddrzewo x
if( y->left != NULL){
y->left->parent = x;
}
y->parent = x->parent; //łaczy starego ojca x i ojca y
if( x->parent == NULL){
root= y;
}
else if( x->key == x->parent->left->key){
x->parent->left = y;
}
else
x->parent->right = y;
y->left = x;
x->parent = y;
return root;
}
Node* leftRotate(Node *root,Node *y)
{
Node *x;
x = y->left;
y->left = x->right;
if ( x->right != NULL)
{
x->right->parent = y;
}
x->parent = y->parent;
if( y->parent == NULL)
{
root = x;
}
else if( y->key == y->parent->left->key)
{
y->parent->left = x;
}
else
y->parent->right = x;
x->right = y;
y->parent = x;
return root;
}
Node *insertBST(Node *root,Node *temp)
{
if (root == NULL) {
return temp;
}
if (temp->key < root->key) {
root->left = insertBST(root->left, temp);
root->left->parent= root;
}
else if (temp->key > root->key) {
root->right = insertBST(root->right, temp);
root->right->parent = root;
}
return root;
}
Node* fixRBT(Node *root, Node *z) {
Node *y;
while ( z!= root && z->parent->color == 'R')
{
if (z->parent->key == z->parent->parent->left->key)
{
y = z->parent->parent->right;
if (y->color == 'R')
{
z->parent->color = 'B';
y->color = 'B';
z->parent->parent->color = 'R';
z = z->parent->parent;
}
else if (z->key == z->parent->right->key)
{
z = z->parent;
root = leftRotate(root,z);
}
z->parent->color = 'B';
z->parent->parent->color = 'R';
root=rightRotate(root,z->parent->parent);
}
else {
y = z->parent->parent->left;
if (y->color == 'R') {
z->parent->color = 'B';
y->color = 'B';
z->parent->parent->color = 'R';
z = z->parent->parent;
}
else if (z->key == z->parent->left->key)
{
z = z->parent;
root=rightRotate(root,z);
}
z->parent->color = 'B';
z->parent->parent->color = 'R';
root=leftRotate(root,z->parent->parent);
}
}
root->color = 'B';
return root;
}
void insert(int key) {
Node *temp = createNode(key);
tree = insertBST(tree, temp);
tree=fixRBT(tree, temp);
}
void inorder(struct Node* root)
{
struct Node* temp = root;
if (temp != NULL)
{
inorder(temp->left);
printf(" %d-%c ",temp->key,temp->color);
inorder(temp->right);
}
return;
}
int main() {
insert(38);
insert(31);
insert(39);
inorder(tree);
return 0;
}

Linked List in C

Although not requirement of my course, I am trying to implement single and double linked list to ensure I understand the concepts. I have worked out most of the issues I think except for one that I have tried to debug and printf my way out of. Although I have read different posts I cannot find out why they are not working similarly.
One my insert function when the while(h != NULL) kicks out I have to check the last item one more time because it would skip it. I thought about a do/while loop but that would not work.
I have the exact same loop for the search function and it finds the last item in the list using while(h != NULL) instead of kicking me before processing it.
Here is the loop that works from the search function,
while(h != NULL) //check list
if(h->val == s)
return true;
else
h = h->next;
Here is the loop that does not from the insert function, this one does not end up using the final value in the linked list before exiting the loop. If you read in the full code before I had to check if if (t->next == NULL && t->val > n) to get it to search the last item.
while(t->next != NULL) //assigns it in the middle
{
if(t->val < n)
t = t->next;
else
{
node* tt = t->prev;
tt->next = a;
a->next = t;
a->prev = t->prev;
t->prev = a;
return h; //returns original
}
}
Thanks in advance and hopefully I am explaining it. Difficult as I am attempting to learn what I do not know.
#include <stdio.h>
#include <stdlib.h> //for rand();
#include <stdbool.h> //bool function
typedef struct _node
{
int val;
struct _node* next;
struct _node* prev;
} node;
node* create(int n, node* h);
node* insert(int n, node* h);
bool search(int s, node* h);
void print(node* h);
void del(node* h);
int main()
{
node* h = NULL;
for(int i = 0; i < 15; i++)
{
int n = rand() % 15;
h = create(n, h);
}
print(h);
int s = 10; //number to search for
if(search(s, h))
printf("Found Item\n");
else
printf("Item not found\n");
del(h);
}
bool search(int s, node* h)
{
if(h == NULL)
printf("No nodes created to search.\n");
while(h != NULL) //check list
if(h->val == s)
return true;
else
h = h->next;
return false;
}
void del(node* h)
{
node* t = h;
while (h->next != NULL)
{
t = h->next;
h->next = NULL;
free(h);
h = t;
}
free(h);
}
node* insert(int n, node* h)
{
node* a = malloc(sizeof(node));
node* t = h;
if(a == NULL)
{
printf("Failed to create new node\n");
return NULL;
}
a->val = n; //sets new node to have value of n
if(h->val >= n) //assigns the integer to the beginning
{
a->next = t;
t->prev = a;
a->prev = NULL;
h = a; //assigns a new head since it appended the item to the beginning
return h;
}
while(t->next != NULL) //assigns it in the middle
{
if(t->val < n)
t = t->next;
else
{
node* tt = t->prev;
tt->next = a;
a->next = t;
a->prev = t->prev;
t->prev = a;
return h; //returns original
}
}
if (t->next == NULL && t->val > n) //check to see if second to last
{
node* tt = t->prev;
tt->next = a;
a->next = t;
a->prev = t->prev;
t->prev = a;
}
else
{
a->next = NULL;
a->prev = t;
t->next = a;
}
return h;
}
node* create(int n, node* h)
{
if(h == NULL) //create first node in the list
{
h = malloc(sizeof(node));
if(h == NULL)
{
printf("Failed to create first node\n");
return NULL;
}
h->val = n;
h->next = NULL;
h->prev = NULL;
}
else //create additional nodes in the list
h = insert(n, h);
return h;
}
void print(node* h)
{
if(h == NULL)
printf("List is empty\n");
else
while(h != NULL)
{
printf("%i\n", h->val);
h = h->next;
}
}
If I understand your question correctly, you are asking about these lines:
while(t->next != NULL) //assigns it in the middle
{
if(t->val < n)
t = t->next;
else
{
node* tt = t->prev;
tt->next = a;
a->next = t;
a->prev = t->prev;
t->prev = a;
return h; //returns original
}
}
if (t->next == NULL && t->val > n) //check to see if second to last
{
node* tt = t->prev;
tt->next = a;
a->next = t;
a->prev = t->prev;
t->prev = a;
}
else
{
a->next = NULL;
a->prev = t;
t->next = a;
}
and the question is: "How can to avoid repeating the code block from inside the while after the while"
Maybe something like this:
while(1)
{
if(t->val < n)
{
if (t->next == NULL) break;
t = t->next;
}
else
{
//assigns it in the middle
node* tt = t->prev;
tt->next = a;
a->next = t;
a->prev = t->prev;
t->prev = a;
return h; //returns original
}
}
// Add new node at the end
a->next = NULL;
a->prev = t;
t->next = a;

Big-O for using a for loop to insert into an AVL

I was writing a code sample for a company I applied for, and they asked that my code run in O(n) in the worst case. I decided to use an AVL tree, but to insert the values I was being given into the AVL tree I had to use a nested loop structure. Does that make my code run in O(n2) in the worst case or does it run in O(n log n)?
EDIT: here is a link to the code on my github: https://github.com/hsleiman1/Algorithms/blob/master/equilibriumIndexAVL.c
My code:
int equilibriumIndex(int A[], int N) {
int i, newRoot = 1;
while (newRoot < N) {
node *leftTree = NULL;
node *rightTree = NULL;
for (i = 0; i < N; i++) {
if (i == newRoot) continue;
if (i < newRoot) leftTree = insert(leftTree, A[i]);
if (i >= newRoot) rightTree = insert(rightTree, A[i]);
}
if (addSubTree(leftTree) == addSubTree(rightTree)) return newRoot;
free(leftTree);
free(rightTree);
newRoot++;
}
return 0;
}
int addSubTree(node *subTree) {
if (subTree == NULL)
return 0;
else
return (subTree->value * subTree->repeat) + addSubTree(subTree->left) + addSubTree(subTree->right);
}
node *leafInit(node *leaf, int key) {
leaf = (node*)malloc(sizeof(node));
if (leaf != NULL) {
leaf->value = key;
leaf->left = NULL;
leaf->right = NULL;
leaf->repeat = 1;
}
return leaf;
}
node *insert(node *leaf, int key) {
if (leaf == NULL)
leaf = leafInit(leaf, key);
else if (key < leaf->value)
leaf->left = insert(leaf->left, key);
else
if (key > leaf->value)
leaf->right = insert(leaf->right, key);
else
leaf->repeat++;
leaf = rotate(leaf, key);
return leaf;
}
node *rotate(node *subTree, int key) {
node *temp;
int balance = getBalance(subTree);
if (balance < -1) {
temp = subTree->left;
if (key > temp->value) {
subTree->left = rightRotate(subTree->left);
subTree = leftRotate(subTree);
}
} else
if (balance > 1) {
temp = subTree->right;
if (key < temp->value) {
subTree->right = leftRotate(subTree->right);
subTree = rightRotate(subTree);
}
} else
if (balance < -1 && key < subTree->value)
subTree = leftRotate(subTree);
else
if (balance > 1 && key > subTree->value)
subTree = rightRotate(subTree);
return subTree;
}
node *leftRotate(node *leaf) {
node *x = leaf->left;
node *y = x->right;
x->right = leaf;
leaf->left = y;
return x;
}
node *rightRotate(node *leaf) {
node *x = leaf->right;
node *y = x->left;
x->left = leaf;
leaf->right = y;
return x;
}
int height(node *leaf) {
if (leaf == NULL) return 0;
else return max(height(leaf->left), height(leaf->right)) + 1;
}
int max(int num, int num1) {
if (num < num1) return num1;
else return num;
}
int getBalance(node *leaf) {
return height(leaf->right) - height(leaf->left);
}
Using an AVL tree will never get you an O(n) complexity. If you do it right, which can be tricky, you will get O(n.log(n)), and if you miss, you may get a degenerate tree and a complexity of O(n2).
For an O(n) complexity, they are expecting you to use a hash table.

Resources