I am creating an AVL for an assignment, but when ever I call the rotate right and rotate left functions the executable crashes with no error message. I think it might be due to a NULL pointer exception but I'm not sure.
Here is my code for the rotations:
TNODE *rotate_right(TNODE *y){
TNODE *x=y->left;
TNODE *t2=x->right;
x->right=y;
y->left=t2;
y->height =max(height(y->left),height(y->right))+1;
x->height=max(height(x->left),height(x->right))+1;
}
TNODE *rotate_left(TNODE *x){
TNODE *y=x->right;
TNODE *t2=y->left;
y->left=x;
x->right=t2;
y->height =max(height(y->left),height(y->right))+1;
x->height=max(height(x->left),height(x->right))+1;
}
And here is the insert function I call them in:
void insert(TNODE **rootp, char *name, float score){
TNODE *np = (TNODE *) malloc(sizeof(TNODE));
if (np == NULL) return;
strcpy(np->data.name, name);
np->data.score = score;
np->height = 1;
np->left = NULL;
np->right = NULL;
// 1. Perform the normal BST insertion
if (*rootp == NULL) {
*rootp = np;
return;
}
TNODE *root = *rootp;
if (strcmp(name, root->data.name) < 0 ){
insert(&root->left, name, score);
}
else if (strcmp(name, root->data.name) > 0 ){
insert(&root->right, name, score);
}
else return ;
// 2. update height of this root node
// add your code here
root->height=height(root);
// STEP 3: get the balance factor of this root node
// add your code here
int balance=balance_factor(root);
// STEP 4: re-balance if not balanced
// add your code here
if(balance>1&&balance_factor(root->left)>=0){
rotate_right(root);
}
else if(balance>1&&balance_factor(root->left)<0){
rotate_left(root->left);
rotate_right(root);
}
else if(balance<-1&&balance_factor(root->right)>=0){
rotate_left(root);
}
else if(balance<-1&&balance_factor(root->right)<0){
rotate_right(root->right);
rotate_left(root);
}
}
The code runs fine if I comment out the last part where I have to rotate it so I'm quite sure the problem is there. Thanks in advance for any help.
Related
I'm performing binary tree deletion in c.I was trying out few methods interestingly this weird situation came.
void Delete(){
struct BinaryTree* ptr = root;
int element;
printf("Enter element to delete : ");
scanf("%d",&element);
while(ptr){
if(element>ptr->data)
ptr = ptr->right;
else if(element<ptr->data)
ptr = ptr->left;
else
break;
}
if(ptr->left && ptr->right){
struct BinaryTree **smallest = &(ptr);
smallest = &((*smallest)->right);
while((*smallest)->left){
smallest = &((*smallest)->left);
}
ptr->data = (*smallest)->data;
free(*smallest);
*smallest = NULL;
} else if(ptr->left){
/*rest cases*/
}
}
The above code works and it sets the the NODE to NULL.
But when i do this procedure in this way it doesn't set to NULL.
if(ptr->left && ptr->right){
struct BinaryTree *smallest = ptr;
smallest = smallest->right;
while(smallest->left){
smallest = smallest->left;
}
ptr->data = smallest->data;
struct BinaryTree **refsmall = &smallest;
free(*refsmall);
*refsmall = NULL;
}
Aren't these two methods are same? If not can someone explain me how they are different?Why the first method work and second didn't?
You should avoid using global variables in your code. If you really want to use globals the first version of delete should look like this:
void Delete(){
/* at some point you will need to change the 'real' root, not the copy of it */
struct BinaryTree **ptr = &root;
int element;
printf("Enter element to delete : ");
scanf("%d",&element);
while(*ptr){
if(element > (*ptr)->data)
ptr = &(*ptr)->right;
else if(element < (*ptr)->data)
ptr = &(*ptr)->left;
else
break;
}
if((*ptr)->left && (*ptr)->right){
struct BinaryTree **smallest = ptr;
smallest = &(*smallest)->right;
while((*smallest)->left){
smallest = &(*smallest)->left;
}
(*ptr)->data = (*smallest)->data;
free(*smallest);
*smallest = NULL;
} else if((*ptr)->left){
/*rest cases*/
}
}
In the first version you would not be able to delete the root.
struct node {
struct node *l,*r;
int data;
};
void delnode(struct node **pp, int data)
{
struct node *del, *l,*r;
// Walk the tree
while(*pp) {
if ((*pp)->data < data) {pp = &(*pp)->l; continue;}
if ((*pp)->data > data) {pp = &(*pp)->r; continue;}
break; // found it!
}
if (!*pp) return; // not found
del = *pp;
l = del->l;
r = del->r;
// If only one child it wil take del's place.
if (!r) *pp = l;
else if (!l) *pp = r;
// del has two children.
// pick one (R) child, and append the (L) other onto its (Leftmost) shoulder
else {
*pp = r;
for (pp= &del->r; *pp; pp=&(*pp)->l) {;} // find Leftmost NULL pointer in the R tree
*pp = l;
}
free(del);
}
I am working on an algorithm to delete a node with a given key from a binary search tree. So far, I have been able to come up with the following code:
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <time.h>
typedef int ElType;
typedef struct Tree {
ElType key;
struct Tree *left;
struct Tree *right;
struct Tree *parent;
} Tree;
Tree* InsertBST(Tree* t, int k)
{
if (t == NULL) {
Tree* w = (Tree*) malloc(sizeof(Tree));
w->key = k;
w->left = NULL;
w->right = NULL;
w->parent = NULL;
return w;
}
if (k <= t->key) {
t->left = InsertBST(t->left, k);
t->left->parent = t;
}
else {
t->right = InsertBST(t->right, k);
t->right->parent = t;
}
return t;
}
Tree* DeleteMaxOfBST(Tree* t, ElType *deleted_value)
{
if (t == NULL) {
*deleted_value = -1;
return NULL;
}
if (t->right == NULL) {
*deleted_value = t->key;
Tree* w = t->left;
w->parent = t->parent;
free(t);
return w;
}
t->right = DeleteMaxOfBST(t->right, deleted_value);
return t;
}
Tree* DeleteNodeOfBST(Tree* t, int k)
{
if (t == NULL) return NULL;
if (k < t->key) {
t->left = DeleteNodeOfBST(t->left, k);
return t;
}
else if (k > t->key) {
t->right = DeleteNodeOfBST(t->right, k);
return t;
}
else if (t->left == NULL) {
Tree* w = t->right;
w->parent = t->parent;
free(t);
return w;
}
else {
ElType max_left;
t->left = DeleteMaxOfBST(t->left, &max_left);
t->key = max_left;
return t;
}
}
The general idea is that I want to work with a BST with pointers to parent nodes and be able to delete a node with whichever key I specify while preserving the structure of a BST.
My code works for some keys in some trees but crashes for other keys without any apparent pattern. I then get the following error:
Segmentation fault (core dumped)
I am inclined to think I have messed up the pointers to the parent nodes but cannot quite pinpoint where the fault is. I am relatively new to C, so I would appreciate any comments whether pointers are in fact the problem here and how to possibly fix this.
So, without any examples of how your code runs it's hard to say where exactly the segmentation fault is occurring when your program is running. When your program encounters a segmentation fault that means that the program is attempting to access memory that, for whatever reason, it is unable to. This generally means your pointers are trying to point at an address in memory that they shouldn't be.
My suggestion would be to run the code step by step and see where the problem occurs. Or find a debugger that can show you the memory issues your program is having. I know that the program Valgrind exists for Ubuntu and other Linux best machines, but I'm not sure what others are available for other OSes. You can read more about Valgrind here: http://valgrind.org/. I use it whenever I need to check for potential memory handling issues in my programs.
Other than that, just keep a real close eye on the space that you create using malloc, as well as where your pointers are pointing. Make sure to reconnect your tree properly when you delete the given node. Manually handling memory can be a pain, but you'll get the hang of it.
Here is the source code for C Program for Insertion and Deletion in Binary Search Tree Recursive..................
/* C Program for Insertion and Deletion in Binary Search Tree Recursive */
#include<stdio.h>
#include<stdlib.h>
struct node
{
struct node *lchild;
int info;
struct node *rchild;
};
struct node *insert(struct node *ptr, int ikey);
void display(struct node *ptr,int level);
struct node *del(struct node *ptr, int dkey);
int main( )
{
struct node *root=NULL,*ptr;
int choice,k;
while(1)
{
printf("\n");
printf("1.Insert\n");
printf("2.Delete\n");
printf("3.Display\n");
printf("4.Quit\n");
printf("\nEnter your choice : ");
scanf("%d",&choice);
switch(choice)
{
case 1:
printf("Enter the key to be inserted : ");
scanf("%d",&k);
root = insert(root, k);
break;
case 2:
printf("Enter the key to be deleted : ");
scanf("%d",&k);
root = del(root,k);
break;
case 3:
display(root,0);
break;
case 4:
exit(1);
default:
printf("\nWrong choice\n");
}/*End of switch */
}/*End of while */
return 0;
}/*End of main( )*/
struct node *insert(struct node *ptr, int ikey )
{
if(ptr==NULL)
{
ptr = (struct node *) malloc(sizeof(struct node));
ptr->info = ikey;
ptr->lchild = NULL;
ptr->rchild = NULL;
}
else if(ikey < ptr->info) /*Insertion in left subtree*/
ptr->lchild = insert(ptr->lchild, ikey);
else if(ikey > ptr->info) /*Insertion in right subtree */
ptr->rchild = insert(ptr->rchild, ikey);
else
printf("\nDuplicate key\n");
return ptr;
}/*End of insert( )*/
void display(struct node *ptr,int level)
{
int i;
if(ptr == NULL )/*Base Case*/
return;
else
{
display(ptr->rchild, level+1);
printf("\n");
for (i=0; i<level; i++)
printf(" ");
printf("%d", ptr->info);
display(ptr->lchild, level+1);
}
printf("\n");
}/*End of display()*/
struct node *del(struct node *ptr, int dkey)
{
struct node *tmp, *succ;
if( ptr == NULL)
{
printf("dkey not found\n");
return(ptr);
}
if( dkey < ptr->info )/*delete from left subtree*/
ptr->lchild = del(ptr->lchild, dkey);
else if( dkey > ptr->info )/*delete from right subtree*/
ptr->rchild = del(ptr->rchild, dkey);
else
{
/*key to be deleted is found*/
if( ptr->lchild!=NULL && ptr->rchild!=NULL ) /*2 children*/
{
succ=ptr->rchild;
while(succ->lchild)
succ=succ->lchild;
ptr->info=succ->info;
ptr->rchild = del(ptr->rchild, succ->info);
}
else
{
tmp = ptr;
if( ptr->lchild != NULL ) /*only left child*/
ptr = ptr->lchild;
else if( ptr->rchild != NULL) /*only right child*/
ptr = ptr->rchild;
else /* no child */
ptr = NULL;
free(tmp);
}
}
return ptr;
}/*End of del( )*/
Hope it may help you. For more details, Visit here for More Operations on Binary Search tree ---> C Program for Insertion and Deletion in Binary Search Tree Recursive
and C Program for binary search tree deletion without recursion
I'm trying to write an implementation for a Red Black Tree algorithm in C but after executing function insert() I get a crash and program stops working. This function firstly find a place in which new value should be added and then it execute another function called Correct_Tree which is responsible for correcting nodes with right order and colors.
There are few warnings I get but don't know how too fix them, other functions built in same way work fine.
|69|warning: conflicting types for 'correct_tree' [enabled by default]|
|40|note: previous implicit declaration of 'correct_tree' was here|
Same warnings point to function Rot_L, I don't know if this warnings cause my crashes. I will be thankful for every answer, if you need more information, let me know. Sorry for my english, I'm not a native speaker.
Here are these functions: http://ideone.com/hsYyES
and structure looks like this:
struct node {
int value;
int key_amounts;
char color;
struct node *parent;
struct node *left;
struct node *right;
} *root;
int insert(int n, struct node *start) {
//if node doesnt exist then add it to the tree otherwise increase amount of keys
//if tree is empty add root
if (root == NULL) {
root = (struct node*)malloc(sizeof *root);
root->value = n;
root->keys_amount = 0;
root->left = NULL;
root->right = NULL;
root->up = NULL;
} else
if (search(root, n) != NULL) {
struct node *tmp = search(root, n);
tmp->keys_amount += 1;
return 0;
} else
//if value is lower than root val then go to left son
if (n < start->value) {
//if left son exist then apply function insert for it
if (start->left != NULL) {
insert(n, start->left);
} else {
//if it doesnt exist then create
struct node *new = (struct node*)malloc(sizeof *root);
new->value = n;
new->keys_amount = 0;
new->left = NULL;
new->right = NULL;
new->up = start;
start->left = new;
correct_tree(new);
}
} else {
//if new value is higher than root
//if right son exist then apply function for it
if (start->right != NULL) {
insert(n, start->right);
} else {
//if it doesnt exist create new one
struct node *new = (struct node*)malloc(sizeof *root);
new->value = n;
new->keys_amount = 0;
new->left = NULL;
new->right = NULL;
new->up = start;
start->right = new;
correct_tree(new);
}
}
return 0;
}
//////////////////////////////////////////////////////////////////
void correct_tree(struct node *start) {
struct node *tmp = (struct node*)malloc(sizeof *root);
start->color = 'R';
while ((start != root) && (start->up->color == 'R')) {
if (start->up == start->up->up->left) {
tmp = start->up->up->right; //uncle of start for tmp
if (tmp->color == 'R') { //case 1
start->up->color = 'B';
tmp->color = 'B';
start->up->up->color='R';
start = start->up->up;
continue;
}
if (start == start->up->right) { //case 2
start = start->up;
rot_L(start);
}
start->up->color = 'B'; //case3
start->up->up->color = 'R';
rot_R(start->up->up);
break;
} else { //mirror cases
tmp = start->up->up->left;
if (tmp->color == 'R') { //case 1
start->up->color = 'B';
tmp->color = 'B';
start->up->up->color = 'R';
start = start->up->up;
continue;
}
if (start == start->up->left) { //case 2
start = start->up;
rot_R(start);
}
start->up->color = 'B'; //case3
start->up->up->color = 'R';
rot_L(start->up->up);
break;
}
}
root->color = 'B';
}
//////////////////////////////////////////////////////////////
void rot_L(struct node *start) {
struct node *tmp = (struct node*)malloc(sizeof *root);
struct node *tmp2 = (struct node*)malloc(sizeof *root);
tmp = start->right;
if (tmp != NULL) {
tmp2 = start->up;
start->right = tmp->left;
if (start->right != NULL)
start->right->up = start;
tmp->left = start;
tmp->up = tmp2;
start->up = tmp;
if (tmp2 != NULL) {
if (tmp2->left == start)
tmp2->left = tmp;
else
tmp2->right = tmp;
} else
root = tmp;
}
}
The warnings issued by the compiler tell you that you did not declare nor define correct_node before calling it. The prototype inferred by the compiler from the call is int correct_tree(struct node *start); which is incompatible with the actual definition it encounters later: void correct_tree(struct node *start). Same problem for rot_L(). Declare all functions before calling them.
Function correct_node is bound to fail because you dereference the up links without first checking that they are not NULL. For example the first time you call correct_node on theleftorrightchild of theroot` node, you have:
start->color = 'R';
while ((start != root) && (start->up->color == 'R')) {
if (start->up == start->up->up->left) {
You do not initialize the color of the root node allocated by malloc(). There is a small chance that root->color may be equal to 'R', which will cause start->up->up->left to have undefined behavior as start->up->up is NULL.
Another issue is this:
struct node *tmp = (struct node*)malloc(sizeof *root);
The object allocated for tmp is never used, never freed and tmp is overwritten in the loop. This is a blatant case of memory leak.
The same issue is present twice in rot_L, for tmp and tmp2.
So I am trying to learn how to create a binary tree in C so far I have got this.
void addRecordsToTree(struct date *in, struct date *root) {
if (root == NULL) {
root = malloc(sizeof(struct date));
root = in;
return;
} else {
//Right side of tree processing
if (compareTwoRecords(in, root) >= 0) {
addRecordsToTree(in, root->right);
return;
} else {
root->right = in;
return;
}
//Left side of tree processing.
if (compareTwoRecords(in, root) < 0) {
addRecordsToTree(in, root->left);
return;
} else {
root->left = in;
return;
}
}
}
int main() {
loadFiles();
struct date treeRoot;
struct date *old = malloc(sizeof(struct date));
old = loadContentsIntoHeap(files[file2014]);
addRecordsToTree(&old[0], &treeRoot);
addRecordsToTree(&old[1], &treeRoot);
addRecordsToTree(&old[2], &treeRoot);
addRecordsToTree(&old[3], &treeRoot);
addRecordsToTree(&old[4], &treeRoot);
addRecordsToTree(&old[5], &treeRoot);
printRecord(7, old);
return 0;
}
The problem is when I check the state of the program in a debugger there is just jumbled up data. I think it could be a type problem somewhere, I find pointers are bit of a mind boggling concept. Im not sure if I have used them right. So here is a screen shot of the debugger.
As you can see at the bottom struct called 'old' is the data I am trying to make the tree out of and treeRoot is where I am trying to place it but I can't understand why I get these garbage values.
Also what is up with the memory address of left and right? am I not creating them correctly.
Another observation I made is when I watch my code in the debugger it seems that root is never == NULL and never gets set, why?
You just did the following:
int x = 2;
int y = x;
y = 5;
Is the second line here necessary or the third one. It is a totally illogical program if you did this. You just did the same thing with a pointer instead of integer. You firstly had a pointer to the base address of dynamic memory then you just overwrote it by initializing it the second time.
And, the iterative approach is far better in comparison to the recursive one. I share the code for inserting a node in a binary tree both recursively and iteratively:
void insert(struct node *temp, struct node **root)
{
while (*root != NULL)
root = (*root)->element < temp->element ? &(*root)->left : &(*root)->right;
*root = temp;
}
#if 0
/* Recursive approach */
void insert(struct node *temp, struct node **root)
{
if(*root == NULL)
*root = temp;
else if ((*root)->element < temp->element)
insert(temp, &(*root)->left);
else
insert(temp, &(*root)->right);
}
#endif
void create_node(int x, struct node **root)
{
struct node *temp = (struct node *) malloc(sizeof(struct node));
if (temp == NULL)
printf("Unable to allocate memory. Free some space.\n");
else
{
temp->left = NULL;
temp->right = NULL;
temp->element = x;
insert(temp, root);
}
}
int main()
{
struct node *root = NULL;
create_node(1, &root);
create_node(2, &root);
create_node(3, &root);
return 0;
}
I saw an additional Problem in your "addRecordsToTree"-function:
the IF-block of the
"//Right side of tree processing"
will allways return from the function. regardless wether the "IF"-Expression is true or false.
So your left-leaves of thew tree will never be inserted. So you probalby should check/debug that function.
i am trying to write a program that will do the following
-read a file from std in
-read each line, and add each line to a binary tree
*if name is already in binary tree,dont add the name to the tree again but update its count of repititions
-print out the binary tree
the file being read in looks something like
dylan
bob
dylan
randall
randall
so when i print out the binary tree i would like it to print out
bob 1
dylan 2
randall 2
i was able to successfully print out the names without worrying about repetitions. I have commented out the blocks of code that mess my program up which is anything interacting with my search function that i added after the fact to take care of repetitions. The code builds a binary tree with each "leave" being a structure of 4 parts,the name,thecount,and the pointers to left and right childs.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct node {
char* name;
int count;
struct node* left;
struct node* right;
};
struct node* addNode(char* string);
void insert(struct node *root, char* stringgg);
void preorder(struct node *root);
int search(struct node* leaf,char* string2find);
int main()
{
char buffer[20];
struct node *root = NULL;
while( fgets(buffer, sizeof(buffer), stdin) != NULL )
{
if(root == NULL)
root = addNode(buffer);
else
insert(root,buffer);
}
preorder(root);
}
struct node* addNode(char* string)
{
struct node *temp = malloc(sizeof(struct node));
temp->name = malloc(strlen(string) + 1);
strcpy(temp->name,string);
temp->left = NULL;
temp->right = NULL;
return temp;
}
void insert(struct node *root, char* stringgg)
{
/* int flag = 5;
flag = search(root,stringgg);
if(flag == 1)
return; */
if(strcmp(stringgg,root->name) < 0)
{
if(root->left == NULL)
root->left = addNode(stringgg);
else
insert(root->left, stringgg);
}
else
{
if(root->right == NULL)
root->right = addNode(stringgg);
else
insert(root->right,stringgg);
}
}
/*int search(struct node* leaf,char* string2find)
{
if(strcmp(string2find,leaf->name) == 0)
{
leaf->count = leaf->count + 1;
return 1;
}
else if(strcmp(string2find,leaf->name) < 0)
{
return search(leaf->left,string2find);
}
else
{
return search(leaf->right,string2find);
}
return 0;
} */
void preorder(struct node *root)
{
if(root == NULL)
return;
printf("%s",root->name);
preorder(root->left);
preorder(root->right);
}
the above code prints out all the names even if there already in a tree. I was hoping that someone would be able to point out my search function errors so that it wont cause a segmentation fault when printing. Possible causes may be my inappropriate use of the return function in which i am trying to return to main if flag == 1 which means match was found so dont addnodes. but if flag does not equal 1 no match was found so go about adding nodes.
at main
while( fgets(buffer, sizeof(buffer), stdin) != NULL ){
char *p = strchr(buffer, '\n');
if(p) *p=0;//remove '\n'
at addNode
temp->count = 1;//initialize counter
return temp;
at insert
void insert(struct node *root, char* stringgg){
int cmp_stat = strcmp(stringgg,root->name);
if(cmp_stat == 0)
root->count++;
else if(cmp_stat < 0) {
if(root->left == NULL)
root->left = addNode(stringgg);
else
insert(root->left, stringgg);
} else {
if(root->right == NULL)
root->right = addNode(stringgg);
else
insert(root->right,stringgg);
}
}
at preorder
printf("%s %d\n",root->name, root->count);
The error is in searching for the very first item in the empty tree — you call
search(root, stringgg)
but root is NULL, so in search() you call
strcmp(string2find, leaf->name)
with leaf == NULL and the program crashes.
A cure: do not search BEFORE you update your tree, but rather search TO update it.
struct node* update(struct node* nd, const char* str)
{
int cmp;
// (sub)tree is empty? - create a new node with cnt==1
if(nd == NULL)
return CreateNode(str);
// test if the node found
cmp = strcmp(str, nd->name);
if(cmp == 0) // YES
nd->count ++; // update the counter
else if(cmp < 0) // NO - search in a subtree
nd->left = update(nd->left, str);
else
nd->right = update(nd->right, str);
return nd; // return the updated subtree
}
Then in main() you just update the tree and store it:
root = update(root, buffer);
Actually, the root value will change only once, on the first call, and all subsequent assignments will not change its value. However that makes the code much more readable.