Below is the menu driven program for various operation in BST. The major problem I am getting is when I free function runs in delete function please help and update the given program. Whenever I try to delete any node after insertion, the program abruptly ends. I tried to debug but the problem still persists.
#include <stdio.h>
#include <stdlib.h>
struct btNode
{
int data;
struct btNode *right;
struct btNode *left;
};
int found;
struct btNode *temp2;
struct btNode *create(int);
struct btNode *insert(struct btNode *, int);
void inorder(struct btNode *);
void preorder(struct btNode *);
void postorder(struct btNode *);
void delete (struct btNode *, int);
int main()
{
int choice, item;
struct btNode *root = NULL;
do
{
printf("\nChoose one of the options:\n");
printf("1. Insert 2. Delete 3. Inorder 4. Postorder 5. Preorder 6. Exit\n");
scanf("%d", &choice);
switch (choice)
{
case 1:
printf("\nEnter any number to insert:");
scanf("%d", &item);
root = insert(root, item);
break;
case 2:
printf("\nEnter any number to delete:");
scanf("%d", &item);
delete(root, item);
break;
case 3:
inorder(root);
break;
case 4:
postorder(root);
break;
case 5:
preorder(root);
break;
case 6:
break;
default:
printf("\nWRONG INPUT");
}
} while (choice != 6);
return 0;
}
struct btNode *create(int num)
{
struct btNode *temp1 = (struct btNode *)malloc(sizeof(struct btNode));
temp1->data = num;
temp1->left = NULL;
temp1->right = NULL;
return temp1;
}
struct btNode *search(struct btNode *root, int num)
{
struct btNode *temp1 = root;
while (temp1 != NULL)
{
if (temp1->data == num)
{
found = 1;
return temp1;
}
else
{
if (temp1->data >= num)
{
temp2 = temp1;
temp1 = temp1->left;
}
else
{
temp2 = temp1;
temp1 = temp1->right;
}
}
}
found = 0;
}
struct btNode *insert(struct btNode *root, int num)
{
struct btNode *temp1 = create(num);
if (root == NULL)
{
root = temp1;
printf("%d inserted\n", root->data);
}
else
{
temp2 = root;
while (temp2 != NULL)
{
if (temp2->data >= num)
{
if (temp2->left)
{
temp2 = temp2->left;
}
else
{
temp2->left = temp1;
printf("%d inserted\n", temp2->left->data);
break;
}
}
else
{
if (temp2->right)
{
temp2 = temp2->right;
}
else
{
temp2->right = temp1;
printf("%d inserted\n", temp2->right->data);
break;
}
}
}
}
return root;
}
void delete (struct btNode *root, int num)
{
struct btNode *temp1 = search(root, num);
if (found == 0)
{
printf("element not found");
return;
}
else
{
if (temp1->left == NULL && temp1->right == NULL)
{
free(temp1);
}
if (temp1->left != NULL && temp1->right == NULL)
{
if (temp2->left = temp1)
{
temp2->left = temp1->left;
free(temp1);
}
if (temp2->right = temp1)
{
temp2->right = temp1->left;
free(temp1);
}
}
if (temp1->left == NULL && temp1->right != NULL)
{
if (temp2->left = temp1)
{
temp2->left = temp1->right;
free(temp1);
}
if (temp2->right = temp1)
{
temp2->right = temp1->right;
free(temp1);
}
}
if (temp1->left != NULL && temp1->right != NULL)
{
struct btNode *node1 = temp1;
struct btNode *node2 = temp1->right;
while (node2->left != NULL)
{
node1 = node2;
node2 = node2->left;
}
temp1->data = node2->data;
temp1 = node2;
free(temp1);
}
}
}
void inorder(struct btNode *r)
{
if (r == NULL)
{
printf("Tree is empty");
return;
}
else
{
if (r->left)
inorder(r->left);
printf("%d ", r->data);
if (r->right)
inorder(r->right);
}
}
void preorder(struct btNode *r)
{
if (r == NULL)
{
printf("Tree is empty");
return;
}
else
{
printf("%d ", r->data);
if (r->left)
preorder(r->left);
if (r->right)
preorder(r->right);
}
}
void postorder(struct btNode *r)
{
if (r == NULL)
{
printf("Tree is empty");
return;
}
else
{
if (r->left)
postorder(r->left);
if (r->right)
postorder(r->right);
printf("%d ", r->data);
}
}
Your delete() function has errors at several levels. Among these:
general API: deletion can change the tree's root node, but you make no provision for that. At minimum deletion changes the root node when the only node of a one-node tree is deleted, but with an approach such as yours, the root node will change whenever you delete the value that it contains.
Implementation flaw: in a similar vein, when you perform a search and discover the target value in the root node, you do not set the (very poorly named) temp2 file-scope variable. When that search is performed in the context of a deletion, it may result in either delete() attempting to dereference a null pointer, or in it corrupting the tree by modifying a random node as if it were the parent on the target node.
Implementation flaw: when you delete a leaf node (other than the root), you need to set its parent's pointer to it to NULL.
Bad code: you have several if statements in delete() that use = where they mean ==.
Poor style: do not rely on global variables (temp2, found). Where you want your functions to return multiple values then either use structures or endow the functions with out parameters.
Here's my code:
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <stdbool.h>
struct node
{
struct node *left;
int data;
struct node *right;
};
struct node *fnode = NULL;
void insert(int val)
{
struct node *ptr = (struct node *) malloc(sizeof(struct node));
struct node *parentptr, *nodeptr;
ptr->data = val;
ptr->left = NULL;
ptr->right = NULL;
if(fnode == NULL)
{
fnode = ptr;
}
else
{
parentptr = NULL;
nodeptr = fnode;
while(nodeptr!=NULL)
{
parentptr = nodeptr;
if(val<nodeptr->data)
nodeptr = nodeptr->left;
else
nodeptr = nodeptr->right;
}
if(val<parentptr->data)
parentptr->left = ptr;
else
parentptr->right = ptr;
}
}
void pre_order(struct node *tree)
{
if(tree!=NULL)
{
printf("%i ",tree->data);
if(tree->left)
pre_order(tree->left);
if(tree->right)
pre_order(tree->right);
}
}
void in_order(struct node *tree)
{
if(tree)
{
in_order(tree->left);
printf("%i ",tree->data);
in_order(tree->right);
}
}
void post_order(struct node *tree)
{
if(tree)
{
post_order(tree->left);
post_order(tree->right);
printf("%i ",tree->data);
}
}
struct node *smallest_element(struct node *tree)
{
if(tree==NULL || tree->left == NULL)
return tree;
else
return smallest_element(tree->left);
}
struct node *largest_element(struct node *tree)
{
if(tree== NULL || tree->right==NULL)
return tree;
else
{
return largest_element(tree->right);
}
}
struct node *delete_element(struct node *tree, int val)
{
// some declarations
struct node *parent, *child;
child = parent = tree;
bool doesnt_exist = false;
// finding the node to be deleted and its corresponding parent
while(child->data!=val)
{
parent = child;
if(val < child->data)
child = child->left;
else
child = child->right;
if(child==NULL)
{
doesnt_exist = true;
break;
}
}
// if no node exists, print not found
if(doesnt_exist)
{
printf("\nThe node does not exist in the BST.");
return tree;
}
// if node exists
else
{
//if parent node is to be deleted
if(child==parent)
{
//if only parent node exists in the tree
if(child->left == NULL && child->right == NULL)
{
free(child);
tree = NULL;
return tree;
}
// deleting the parent node and replacing it by left-subtree's highest element
struct node *temp = tree->left;
struct node *pre_temp = tree->left;
//searching for left subtree's max element and its parent
while(temp->right!=NULL)
{
pre_temp = temp;
temp = temp->right;
}
//changing the deleted node's value with left subtree's highest element
child->data = temp->data;
//making the ex-position of changed element point to null
if(pre_temp->right == temp)
{
pre_temp->right = NULL;
}
else
{
pre_temp->left = NULL;
}
//freeing the ex-position of changed element.
free(temp);
}
else
{
// if the node to be deleted has 2 nodes
if(child->left && child->right)
{
//some declarations
struct node *temp = child->left;
struct node *pretemp = child;
//browsing to the maximum node on left subtree
while(temp->right!=NULL)
{
pretemp = temp;
temp = temp->right;
}
//exchanging left subtree's max with element to be deleted
child->data = temp->data;
//making the temp's parent point to null
if(pretemp->left == temp)
pretemp->left = NULL;
else
pretemp->right = NULL;
//freeing temp;
free(temp);
}
//if the node to be deleted has only right node
else if(child->left == NULL && child->right)
{
if(parent->left==child)
{
parent->left = child->right;
}
else
{
parent->right = child->right;
}
free(child);
return tree;
}
// if the node to be deleted has only left node
else if(child->right==NULL && child->left)
{
if(parent->left==child)
{
parent->left = child->left;
}
else
{
parent->right = child->left;
}
free(child);
return tree;
}
//if the node to be deleted has no children
else
{
if(parent->left == child)
parent->left = NULL;
else
parent->right = NULL;
free(child);
return tree;
}
}
}
}
int main()
{
int decision;
struct node *ptr;
int ip;
do
{
printf("\n ********MAIN MENU********");
printf("\n 1. Insert element");
printf("\n 2. Pre-order Traversal");
printf("\n 3. In-order Traversal");
printf("\n 4. Post-order Traversal");
printf("\n 5. Find smallest element");
printf("\n 6. Find largest element");
printf("\n 7. Delete an element");
printf("\n 8. Exit");
printf("\nEnter your choice:");
scanf("%i",&decision);
switch(decision)
{
case 1:
printf("\nEnter the element to be inserted:");
scanf("%i",&ip);
insert(ip);
break;
case 2:
if(fnode)
{
printf("\nThe pre-order traversal is as follows:\n");
pre_order(fnode);
}
else
{
printf("\nThe BST is empty!!!");
}
break;
case 3:
if(fnode)
{
printf("\nThe in-order traversal is as follows:\n");
in_order(fnode);
}
else
{
printf("\nThe BST is empty!!!");
}
break;
case 4:
if(fnode)
{
printf("\nThe post-order traversal is as follows:\n");
post_order(fnode);
}
else
{
printf("\nThe BST is empty!!!");
}
break;
case 5:
ptr = smallest_element(fnode);
if(ptr)
{
printf("\nThe smallest element is: %i",ptr->data);
}
else
{
printf("\nThe BST is empty!!!");
}
break;
case 6:
ptr = largest_element(fnode);
if(ptr)
{
printf("\nThe largest element is: %i",ptr->data);
}
else
{
printf("\nThe BST is empty!!!");
}
break;
case 7:
printf("\nEnter the element you want to delete:");
scanf("%i",&ip);
fnode = delete_element(fnode,ip);
break;
}
}
while(decision!=8);
return 0;
}
After I delete a node which had two child nodes, the resultant BST is formed properly (I verified it through debug tools). I have added all the possible cases for deleting a node from BST (has 0/1/2 child nodes and I have handled everything).
But when I make it to print the preorder/postorder/inorder traversal, the program just exits. Can u suggest me why is it so?
I tried writing a tree program in C, starting with the insert function as shown below:
void insert(int val)
{
struct node * nn = (struct node *)malloc(sizeof(struct node));
nn->data = val;
nn->left = NULL;
nn->right = NULL;
if(root == NULL)
{
root = nn;
}
else
{
struct node *ptr = root;
while(ptr->left != NULL && ptr->right != NULL)
{
if(nn->data < ptr->data)
{
ptr = ptr->left;
}
else
{
ptr = ptr->right;
}
}
if(ptr->data < nn->data)
{
ptr->right = nn;
}
else
{
ptr->left = nn;
}
}
Then I wrote the code for displaying the nodes of the tree so formed:
void display()
{
struct node *n;
if(root == NULL)
{
printf("Tree is Empty\n");
}
else
{
n = root;
if(n!=NULL)
{
printf("%d",n->data);
display(n->left);
display(n->right);
}
}
}
This is the main function:
int main()
{
int ch,val;
while(ch!=3)
{
printf("1. Insert\n2. Display\n3. Exit\nEnter your choice: ");
scanf("%d",&ch);
switch(ch)
{
case 1:
printf("Enter value to be inserted: ");
scanf("%d",&val);
insert(val);
break;
case 2:
display();
break;
case 3:
ch=3;
printf("Exiting....\n");
break;
default:
printf("Invalid choice, please try again\n");
break;
}
}
return 0;
}
But when I tried executing the display function after inserting a few nodes, it only printed the first node in an infinite loop.
Could someone please help me get around this problem?
With each iteration (recursion) you start with root again. That will continue forever, of course.
Your function signature should be
void display(struct node *n)
and then call it in main as:
display(root);
Fixing the display function itself with this feed back I leave to you.
EDIT: the function should be:
void display(struct node *n)
{
if (n) {
printf("%d\n",n->data);
display(n->left);
display(n->right);
}
}
I did a program in c to do some avl sorting. the program runs well when i test it with no crash. however i ran the program for possible bugs with afl fuzzer and i dont seem to know why i keep getting segmentation fault. below is the tree.c. I dont get bugs when i fuzz without my main.c connecting to the tree.c. Only comes when i send inputs to the tree sorter. Some certain inputs brings about this bug. i made changes to memory allocation but still cant figure out why. i used valgrind, cppcheck and dont get any errors on them. Please why does this error happen and how can i fix it?
an example input from the fuzzer that brings code to segmentation fault
i 3o
i 7ÿo
i
i 3ÿo
i3
3
i 3ÿ3
i83 3
i23ÿo
tree.c
#include "tree.h"
Tree* tree_create(){
Tree *tree = malloc(sizeof(Tree));
tree->root = NULL;
return tree;
}
void tree_node_delete(Node* node) {
if (node == NULL) {
free(node);
return;
}
if (node->left) {
tree_node_delete(node->left);
}
if (node->right) {
tree_node_delete(node->right);
}
free(node->name);
free(node);
}
void tree_delete(Tree* tree) {
tree_node_delete(tree->root);
free(tree);
}
void node_insert(Node* node, int age, char* name, int gen) {
if (age <= node->age){
if (node->left == NULL){
Node* newLeft = calloc(1, sizeof(Node));
newLeft->age = age;
newLeft->name = name;
newLeft->parent = node;
newLeft->right = NULL;
newLeft->left = NULL;
newLeft->isRight = false;
node->left = newLeft;
} else {
node_insert(node->left, age, name, node->left->generation);
}
} else {
if (node->right == NULL){
Node* newRight = calloc(1, sizeof(Node));
newRight->age = age;
newRight->name = name;
newRight->parent = node;
newRight->right = NULL;
newRight->left = NULL;
newRight->isRight = true;
node->right = newRight;
} else {
node_insert(node->right, age, name, node->right->generation);
}
}
}
void tree_insert(Tree* tree, int age, char* name) {
if (tree->root == NULL) {
Node *node = calloc(1, sizeof(Node));
node->name = name;
node->age = age;
node->isRoot = true;
node->right = NULL;
node->left = NULL;
tree->root = node;
} else {
node_insert(tree->root, age, name, 1);
}
}
void tree_erase(Tree* tree, int age, char* name) {
Node* data = tree_find(tree, age, name);
if (data == NULL) {
printf("\nThis node doesn't exist in the current tree\n");
} else {
data->name = NULL;
data->age = NULL;
if (data->grandparent) {
if(data == data->grandparent->grandchildRR) {
data->grandparent->grandchildRR = NULL;
} else if(data == data->grandparent->grandchildRL) {
data->grandparent->grandchildRL = NULL;
} else if(data == data->grandparent->grandchildLR) {
data->grandparent->grandchildLR = NULL;
} else if(data == data->grandparent->grandchildLL) {
data->grandparent->grandchildLL = NULL;
}
}
tree_cleanup(tree, &tree->root, tree->root);
}
}
// Will clean the tree to release previously used nodes
void tree_cleanup(Tree* tree, Node** nodeAdress, Node* node) {
if (node->left) {
tree_cleanup(tree, &node->left, node->left);
}
if (node->right) {
tree_cleanup(tree, &node->right, node->right);
}
if(node->age == NULL && node->name == NULL) {
*nodeAdress = NULL;
free(*nodeAdress);
}
if(node->left == NULL && node->grandchildLL) {
node->left = node->grandchildLL;
node->left->parent = node;
node->left->grandparent = node->parent;
if(node->left->left) {
node->grandchildLL = node->left->left;
} else {
node->grandchildLL = NULL;
}
} else if(node->right == NULL && node->grandchildRL) {
node->right = node->grandchildRL;
node->right->parent = node;
node->right->grandparent = node->parent;
node->right->isRight = true;
if(node->right->left) {
node->grandchildRL = node->right->left;
} else {
node->grandchildLR = NULL;
}
} else if(node->left == NULL && node->grandchildLR) {
node->left = node->grandchildLR;
node->left->parent = node;
node->left->grandparent = node->parent;
node->left->isRight = false;
if (node->left->right) {
node->grandchildLR = node->left->right;
} else {
node->grandchildLR = NULL;
}
} else if(node->right == NULL && node->grandchildRR) {
node->right = node->grandchildRR;
node->right->parent = node;
node->right->grandparent = node->parent;
if (node->right->right) {
node->grandchildRR = node->right->right;
} else {
node->grandchildRR = NULL;
}
}
}
//Calculate the weight and the balance factor of the node.
void tree_balance_factor(Tree* tree, Node* node) {
if (node == NULL) {
return;
}
if (node->left) {
tree_balance_factor(tree, node->left);
}
if (node->right) {
tree_balance_factor(tree, node->right);
}
if (node->parent) {
if (node->isRight == true) {
if (node->weightRight > node->weightLeft) {
node->parent->weightRight = node->weightRight+1;
} else {
node->parent->weightRight = node->weightLeft+1;
}
} else if (node->isRight == false) {
if (node->weightRight > node->weightLeft) {
node->parent->weightLeft = node->weightRight+1;
} else {
node->parent->weightLeft = node->weightLeft+1;
}
}
}
node->balancefactor = node->weightRight - node->weightLeft;
if (node->balancefactor == 2) {
if(node->right->balancefactor == 1) {
leftRotation(tree, node);
} else {
rightPermutation(tree, node);
leftRotation(tree, node);
}
} else if (node->balancefactor == -2) {
if(node->left->balancefactor == -1) {
rightRotation(tree, node);
} else {
leftPermutation(tree, node);
rightRotation(tree, node);
}
}
}
// Reset the weightings and set up the grandchilds and grandparents relations back
void tree_balance_factor_reset(Tree* tree, Node* node) {
if (node == NULL) {
return;
}
if (node->left) {
tree_balance_factor_reset(tree, node->left);
}
if (node->right) {
tree_balance_factor_reset(tree, node->right);
}
node->weightLeft = 0;
node->weightRight = 0;
if(node->right) {
if(node->right->right) {
node->grandchildRR = node->right->right;
node->right->parent = node;
node->right->right->grandparent = node;
} else {
node->grandchildRR = NULL;
}
if(node->right->left) {
node->grandchildRL = node->right->left;
node->right->parent = node;
node->right->left->grandparent = node;
} else {
node->grandchildRL = NULL;
}
}
if(node->left) {
if(node->left->left) {
node->grandchildLL = node->left->left;
node->left->parent = node;
node->left->left->grandparent = node;
} else {
node->grandchildLL = NULL;
}
if (node->left->right) {
node ->grandchildLR = node->left->right;
node->left->parent = node;
node->left->right->grandparent = node;
} else {
node->grandchildLR = NULL;
}
}
}
void setGen (Node* node) {
if(node->parent) {
node->generation = node->parent->generation +1;
}
if (node->left) {
setGen(node->left);
}
if (node->right) {
setGen(node->right);
}
}
void leftRotation(Tree* tree, Node* node ) {
Node* newNode = node->right;
if(node->isRoot == true) {
tree->root = newNode;
newNode->isRoot = true;
node->isRoot = false;
newNode->parent = NULL;
} else if (node->isRoot = false){
newNode->parent = node->parent;
if(node->isRight) {
newNode->parent->right = newNode;
} else {
newNode->parent->left = newNode;
}
}
newNode->left = node;
node->parent = newNode;
node->right = NULL;
}
void rightRotation(Tree* tree, Node* node) {
Node* newNode = node->left;
if(node->isRoot == true) {
tree->root = newNode;
newNode->isRoot = true;
node->isRoot = false;
newNode->parent = NULL;
} else {
newNode->parent = node->parent;
if(node->isRight) {
newNode->parent->right = newNode;
} else {
newNode->parent->left = newNode;
}
}
newNode->right = node;
node->parent = newNode;
node->left = NULL;
}
void rightPermutation(Tree* tree, Node* node) {
Node* newNode = node->right;
node->right = newNode->left;
node->right->right = newNode;
newNode->left = NULL;
newNode->parent = node->right;
node->right->parent = node;
}
void leftPermutation(Tree* tree, Node* node) {
Node* newNode = node->left;
node->left = newNode->right;
node->left->left = newNode;
newNode->right = NULL;
newNode->parent = node->left;
node->left->parent = node;
}
void tree_print_node(Node* node){
if (node == NULL) {
printf("null");
return;
}
printf("[");
printf("{\"%d\":\"%s\"},", node->age, node->name);
tree_print_node(node->left);
printf(",");
tree_print_node(node->right);
printf("]");
}
void tree_print(Tree* tree, int printNewline){
if (tree == NULL) {
printf("null");
return;
}
tree_print_node(tree->root);
if (printNewline){
printf("\n");
}
}
Node* node_find(Node* node, int age, char* name) {
int i = strcmp(node->name, name);
if (node->age == age && i == 0) {
return node;
}
if (age <= node->age) {
if (node->left) {
return node_find(node->left, age, name);
} else {
return NULL;
}
} else {
if (node->right) {
return node_find(node->right, age, name);
} else {
return NULL;
}
}
}
Node* tree_find(Tree* tree, int age, char* name) {
if(tree->root != NULL) {
return node_find(tree->root, age, name);
} else {
printf("\nNo node inserted in the tree yet\n");
return NULL;
}
}
main.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "main.h"
#include "tree.h"
int main() {
char* commandBuffer = (char*)malloc(sizeof(char) * 20);
Tree *tree = tree_create();
for(;;) {
if (tree == NULL){
tree = tree_create();
}
tree_balance_factor_reset(tree, tree->root);
tree_balance_factor(tree, tree->root);
tree_balance_factor_reset(tree, tree->root);
printf("\n- Enter <i age name> to insert a node in the tree \n- Enter <e age name> to erase a node \n- Enter <c age name> to check the tree \n- Enter <p> to "
"print the tree \n- Enter <x> the delete the tree \n- Enter <q> to exit the program\n\n" );
fgets(commandBuffer, 20, stdin);
int b = strlen(commandBuffer);
if(b>=19) {
int clearVar;
while (((clearVar = getchar()) != '\n' && clearVar != EOF)) {
}
};
// Quit on EOF or 'q'
if (feof(stdin) || *commandBuffer == 'q' ){
break;
}
tree = handleString(commandBuffer, tree);
};
free(tree);
free(commandBuffer);
return 0;
}
Tree* handleString(char command[], Tree *tree){
if (command == NULL){
fprintf(stderr, "Invalid command; null pointer\n");
return tree;
}
switch(command[0]){
case 'i':
insert(command, tree);
break;
case 'e':
erase(command, tree);
break;
case 'c':
check(command, tree);
break;
case 'p':
tree_print(tree, 1);
break;
case 'x':
tree_delete(tree);
return NULL;
default:
fprintf(stderr, "Invalid command string: %s\n", command);
break;
}
return tree;
}
Tree* insert(char* command, Tree* tree) {
int age;
char* name = malloc(sizeof(char) * 20);
if (2 != sscanf(command, "i %d %19s", &age, name)){
fprintf(stderr, "Failed to parse insert command: not enough parameters filled\n");
// return NULL;
}
if (tree == NULL){
tree = tree_create();
}
tree_insert(tree, age, name);
return tree;
}
int erase(char* command, Tree* tree) {
int age;
char* name = malloc(sizeof(char) * 20);
if (2 != sscanf(command, "e %d %19s", &age, name)){
fprintf(stderr, "Failed to parse erase command: not enough parameters filled\n");
// return 0;
}
tree_erase(tree, age, name);
return 0;
}
void check(char* command, Tree* tree) {
int age;
char* name = malloc(sizeof(char) * 20);
if (2 != sscanf(command, "c %d %19s", &age, name)){
fprintf(stderr, "Failed to parse check command\n");
}
Node* result = tree_find(tree, age, name);
if (result){
printf("\nThe node is present\n");
} else {
printf("\nThe node could not be found\n");
}
}
tree.h
#ifndef C_IMPLEMENTATION_TREE_H
#define C_IMPLEMENTATION_TREE_H
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
typedef struct Node {
/**
* Left child of this node
*/
struct Node* left;
/**
* Right child of this node
*/
struct Node* right;
/**
* The age of the data in this node
*/
int generation;
int balancefactor;
int weightLeft;
int weightRight;
struct Node* parent;
struct Node* grandparent;
struct Node* grandchildLL;
struct Node* grandchildLR;
struct Node* grandchildRL;
struct Node* grandchildRR;
bool isRight;
bool parentIsRight;
bool isRoot;
int age;
/**
* The name of the data in this node
*/
char* name;
} Node;
typedef struct Tree {
Node *root;
} Tree;
/**
* Create a new tree
* #param age The age value for the first data point
* #param name The name value for the first data point
* #return The root Node of the tree
*/
Tree* tree_create();
/**
* Delete an entire tree. This will delete the passed Node and all children below it
* #param node The root Node of the tree to delete.
*/
void tree_delete(Tree* tree);
/**
* Insert a new data point into the tree
*
* #param tree The root node of the tree
* #param age The age part of the data point
* #param name The name part of the data point
*/
void tree_insert(Tree* tree, int age, char* name);
/**
* Remove a data point from a tree
* #param tree The root node of the tree
* #param age The age part of the data point to delete
* #param name The name part of the data point to delete
*/
void tree_erase(Tree* tree, int age, char* name);
/**
* Prints a tree in the following format:
* [<data>, <left>, <right>]
* where the elements above have the following format:
* <data> {<age:int>: "<name:string>"}
* <left>, <right>: The same format as the root node. When a child node is NULL, the string NULL is to be printed.
*/
void tree_cleanup(Tree* tree, Node** nodeAdress, Node* node);
/**
* Will free and release null nodes.
*/
void setGen(Node* node);
void tree_balance_factor(Tree* tree,Node* node);
void tree_balance_factor_reset(Tree* tree, Node* node);
void leftRotation(Tree* tree, Node* node);
void rightRotation(Tree* tree,Node* node);
void rightPermutation(Tree* tree, Node* node);
void leftPermutation(Tree* tree, Node* node);
void tree_print(Tree *tree, int printNewline);
Node* tree_find(Tree* node, int age, char* name);
#endif //C_IMPLEMENTATION_TREE_H
I managed to reproduce SIGSEGV in gdb. It is hapened in function rightPermutation, which does not check if pointer to left is NULL or not:
void rightPermutation(Tree* tree, Node* node) {
Node* newNode = node->right;
node->right = newNode->left;
In case the node->left is NULL, you will get SIGSEGV on next line:
node->right->right = newNode;
Further, you can see details of the message and data of the Node structure.
Program received signal SIGSEGV, Segmentation fault.
0x000055555555570c in rightPermutation (tree=0x555555758280, node=0x555555758d20) at tree.c:322
322 node->right->right = newNode;
(gdb) p node
$1 = (Node *) 0x555555758d20
(gdb) p *node
$2 = {left = 0x555555758ed0, right = 0x0, generation = 0, balancefactor = 2, weightLeft = 1, weightRight = 3, parent = 0x0, grandparent = 0x555555758b70,
grandchildLL = 0x0, grandchildLR = 0x0, grandchildRL = 0x0, grandchildRR = 0x555555758c00, isRight = false, parentIsRight = false, isRoot = true, age = 0,
name = 0x555555758d00 ""}
I have made a working binary tree.
Now I want when I press option # 4, it'll show binary tree is sorted according to the array (that means the middle should be root, the left part of the left subtree, then the right part of the field to the right subtree).
I have created functions required to do what it should be done but still it does not work as it should.
I have created NodSize(), it controls how many nodes are in the tree.
I have created balanceTree(), it takes all that is in the root.
I have created ArrayInorder(),
And Balance(), it makes balancing the tree according to array.
Where did I do wrong and how can I solve it?
..
You can see down here how I made it:
#include<stdio.h>
#include<conio.h>
#include<stdlib.h>
#include<math.h>
#include<string.h>
#define MAX 100
struct tree
{
int data;
struct tree *left;
struct tree *right;
};
struct tree *CreateNode(int data)
{
struct tree *node = (struct tree*) malloc(sizeof(struct tree));
if (node != NULL)
{
node->data = data;
node->left = NULL;
node->right = NULL;
}
return node;
}
struct tree *insert(struct tree *root, int data)
{
if (root == NULL)
{
root = CreateNode(data);
}
if (root->data > data)
{
if (root->left == NULL)
{
root->left = CreateNode(data);
}
else
{
insert(root->left, data);
}
}
else if (root->data < data)
{
if (root->right == NULL)
{
root->right = CreateNode(data);
}
else
{
insert(root->right, data);
}
}
return root;
}
struct tree *delet(struct tree *ptr, int x)
{
struct tree *p1, *p2;
if (!ptr)
{
printf("\n NOTHING ");
return(ptr);
}
else
{
if (ptr->data < x)
{
ptr->right = delet(ptr->right, x);
}
else if (ptr->data > x)
{
ptr->left = delet(ptr->left, x);
return ptr;
}
else
{
if (ptr->data == x)
{
if (ptr->left == ptr->right)
{
free(ptr);
return(NULL);
}
else if (ptr->left == NULL)
{
p1 = ptr->right;
free(ptr);
return p1;
}
else if (ptr->right == NULL)
{
p1 = ptr->left;
free(ptr);
return p1;
}
else
{
p1 = ptr->right;
p2 = ptr->right;
while (p1->left != NULL)
p1 = p1->left;
p1->left = ptr->left;
free(ptr);
return p2;
}
}
}
}
return(ptr);
}
void Findroot(struct tree *root)
{
if (root != NULL)
{
printf("\nRoot is %d\n", root->data);
}
else
{
printf("\nNOTHING\n");
}
}
void inorder(struct tree *root)
{
if (root != NULL)
{
inorder(root->left);
printf(" %d", root->data);
inorder(root->right);
}
return;
}
int NodSize(struct tree *root)
{
if (root == NULL)
return 0;
else
return (NodSize(root->left) + 1 + NodSize(root->right));
}
void DestoryTree(struct tree * root)
{
if (root == NULL)
return;
DestoryTree(root->left);
DestoryTree(root->right);
printf("\n Destory node: %d", root->data);
free(root);
}
struct tree *Balance(int arr[], int start, int end)
{
if (start > end)
return NULL;
int mid = (start + end) / 2;
struct tree *root = CreateNode(arr[mid]);
root->left = Balance(arr, start, mid - 1);
root->right = Balance(arr, mid + 1, end);
return root;
}
int ArrayInorder(struct tree *root, int *arr, int helper)
{
if (root != NULL)
{
helper = ArrayInorder(root->left, arr, helper);
arr[helper] = root->data;
helper++;
helper = ArrayInorder(root->right, arr, helper);
}
return helper;
}
void balanceTree(struct tree *root)
{
int *arr, size;
size = NodSize(root);
arr = (int*)malloc(sizeof(int)*size);
ArrayInorder(root, arr, 0);
//DestoryTree(root);
root = Balance(arr, 0, size - 1);
}
void CreateBalancedTreeFromArray(struct tree *root, int *arr, int size)
{
DestoryTree(root);
root = Balance(arr, 0, size - 1);
}
int main(void)
{
struct tree *root;
int valja, item, dele;
root = NULL;
do
{
do
{
printf("\n1. Add a node to BINARY TREE ");
printf("\n2. Delete a node from BINARY TREE ");
printf("\n3. Show ROOT");
printf("\n4. Show Balanced Tree IN (Array)");
printf("\n5. Stang");
printf("\nYour choice? : ");
scanf(" %d", &valja);
if (valja<1 || valja>5)
printf("\n Fel - Try again");
} while (valja<1 || valja>5);
switch (valja)
{
case 1:
system("cls");
printf("\n Write a new element: ");
scanf("%d", &item);
root = insert(root, item);
printf("\n root is %d \n", root->data);
printf("INORDER: ");
inorder(root);
printf("\n");
break;
case 2:
system("cls");
printf("\n Write an element to delete: ");
scanf(" %d", &dele);
root = delet(root, dele);
printf("\n");
break;
case 3:
system("cls");
Findroot(root);
printf("\n");
break;
case 4:
balanceTree(root);
Findroot(root);
inorder(root);
break;
default:
printf("\n bye ");
}
} while (valja != 5);
return(0);
}
The problem is here:
void balanceTree(struct tree *root)
Although this function works, the new root that is created is NOT returned to the caller because root has been passed by value. You need to change the function to:
struct tree *balanceTree(struct tree *root)
and add this at the end:
return root;
Call the function with:
root = balanceTree(root);