I am having trouble grappling this error. I am implementing a Red black tree in C and am running into segmentation fault at a particular location (line 29)
TNODE *tree_add(TNODE *root, const KEY k, const VALUE v) {
LNODE *lnode = NULL;
if (root == NULL) {
TNODE *node = talloc(k);
lnode = lalloc(v);
node->head = lnode;
node->tail = lnode;
node->is_red = true;
return node;
}
if (strcmp(k, root->key) < 0) {
root->left = tree_add(root->left, k, v);
} else if (strcmp(k, root->key) > 0) {
root->right = tree_add(root->right, k, v);
} else {
if (strcmp(k, root->key) == 0) {
lnode = lalloc(v);
root->tail->next = lnode;
root->tail = lnode;
root->tail->next = NULL;
}
}
if (is_red(root->right) && !is_red(root->left)) { //is_red seg faulting
root = rotate_left(root);
}
if (is_red(root->left) && is_red(root->left->left)) {
root = rotate_right(root);
}
if (is_red(root->left) && is_red(root->right)) {
flip_colors(root);
}
return root;
}
Here is the is_red function:
bool is_red(const TNODE *h) {
bool is_red = h->is_red;
return is_red;
}
Before implementing the last three if statements to convert BST to RB tree, the code works fine. What is weird is that when I debugged is_red, the variable is_red comes up as true. So that means I am not accessing restricted memory. However, I get a seg fault as soon as I return from is_red function and intotree_add.
For further clarification, here is the TNODE struct:
typedef struct tnode {
KEY key; // Search key for this binary search tree node.
struct tnode *right; // Right child.
struct tnode *left; // Left child.
LNODE *head; // Head of the linked list storing the values for the search key.
LNODE *tail; // Tail of the linked list storing the values for the search key.
bool is_red; // Flag use only in red-black trees to denote redness.
} TNODE;
You want to make sure the right child and left child exist before you do the IS_RED check:
Replace
if (is_red(root->right) && !is_red(root->left)) //is_red is giving me seg fault
with
if (root->right && is_red(root->right) && root->left && !is_red(root->left))
Please also do the similar check to other places.
Related
I am getting a segmentation fault when trying to print the nodes in my binary tree. It looks to be an issue with the third node. I have searched google and stack overflow for hours but I can not understand what the problem is. I am trying to teach myself data structures in C and am very much a novice so I may be doing something in a frowned upon way.
#include <stdio.h>
#include <stdlib.h>
typedef struct node
{
int data;
struct node *left;
struct node *right;
} Node;
typedef struct
{
Node *root;
} BinarySearchTree;
void printInOrder(Node *);
void addNode(Node *, Node *);
int main (void)
{
BinarySearchTree tree;
BinarySearchTree *tree_ptr = &tree;
Node n1, n2, n3;
n1.data = 1;
n2.data = 2;
n3.data = 3;
Node *n1_ptr = &n1;
Node *n2_ptr = &n2;
Node *n3_ptr = &n3;
tree_ptr->root = n1_ptr;
addNode(tree_ptr->root, n2_ptr);
addNode(tree_ptr->root, n3_ptr);
printInOrder(tree_ptr->root);
}
void printInOrder(Node *root)
{
if (root == NULL)
{
return;
} else
{
printInOrder(root->left);
printf("%i\n", root->data);
printInOrder(root->right);
}
}
void addNode(Node *root, Node *node)
{
if (node->data < root->data)
{
if (root->left == NULL)
{
root->left = node;
} else
{
addNode(root->left, node);
}
}
else if (node->data > root->data)
{
if (root->right == NULL)
{
root->right = node;
} else
{
addNode(root->right, node);
}
}
}
output:
1
2
Segmentation fault: 11
There doesn't seem to be an issue with any but the third node. If I comment out the line that adds the second node I get the same error (with only 1 being printed, obviously).
Your initialization is incomplete
n1.data = 1;
n2.data = 2;
n3.data = 3;
should also set the pointers
n1.data = 1;
n1.left = NULL;
n1.right = NULL;
n2.data = 2;
n2.left = NULL;
n2.right = NULL;
n3.data = 3;
n3.left = NULL;
n3.right = NULL;
Problem is occurring because you are not initializing all the member of structure Node type variable.
I would suggest, you should write a function to initialize the Node type variable, like this:
void init_node(Node * nodeptr, int data)
{
nodeptr->data = data;
nodeptr->left = NULL;
nodeptr->right = NULL;
}
and in your main() (or from where ever you want to initialize) you can simply do:
init_node(&n1, 1);
init_node(&n2, 2);
init_node(&n3, 3);
With this, you will never miss assigning NULL to left and right pointer during initialization of Node type variable and chances of the error occurring because of it will be reduced to a greater extent.
i was trying to understand this function founded online for deleting a node from a BST. There are some things i can't understand
This is the code :
struct Node* Delete(struct Node *root, int data) {
if (root == NULL) {
return NULL;
}
if (data > root->data) { // data is in the left sub tree.
root->left = Delete(root->left, data);
} else if (data > root->data) { // data is in the right sub tree.
root->right = Delete(root->right, data);
} else {
// case 1: no children
if (root->left == NULL && root->right == NULL) {
delete(root); // wipe out the memory, in C, use free function
root = NULL;
}
// case 2: one child (right)
else if (root->left == NULL) {
struct Node *temp = root; // save current node as a backup
root = root->right;
delete temp;
}
// case 3: one child (left)
else if (root->right == NULL) {
struct Node *temp = root; // save current node as a backup
root = root->left;
delete temp;
}
// case 4: two children
else {
struct Node *temp = FindMin(root->right); // find minimal value of right sub tree
root->data = temp->data; // duplicate the node
root->right = Delete(root->right, temp->data); // delete the duplicate node
}
}
return root; // parent node can update reference
}
Questions :
1) Why it is
if (data > root->data) { // data is in the left sub tree.
root->left = Delete(root->left, data);
shouldn't it be if(data < root->data) ? (same for the two lines of code right after)
2) the function return a pointer to node,does that mean that in the main function i have to do something like this?
int main(){
struct Node *tree=malloc(sizeof(Node));
...
struct Node *new_tree=malloc(sizeof(Node));
new_tree= Delete(tree,24);
So the function replace the old tree with a new tree without the node with the val 24?if i want the function to be of type void should i use double pointers?
For your first question you have right it should be: if(data < root->data).
For the second question not exactly. You obviously should define a pointer head which is the head of the tree and create an function which inserts data to bst, so this function does the malloc. All you nead in your main is the head pointer initialized to NULL in the beginning so it should look like:
int main(){
struct Node *tree=NULL;
int number=...;
...
input_to_bst(&tree,number);
...
new_tree= Delete(tree,24);
Also note that new tree doesn't need to have malloc since your function returns a pointer that already shows to a struct and what you do is that new_tree will also point this struct.
For your final question yes of course you could pass double pointer (in fact I followed this way in the definition of input_to_bst(&tree);).
An example of function input_to_bst definition could be:
void input_to_bst(treeptr* head,int number){
if((*head)==NULL){
(*head)=(treeptr)malloc(sizeof(struct tree));
(*head)->data=number;
(*head)->left=NULL;
(*head)->right=NULL;
}
else{
if(((*head)->data)>number) input_to_bst(&((*head)->left),number);
else (((*head)->data)<number) input_to_bst(&((*head)->right),number);
}
}
where we suppose that we have defined the structs:
struct tree{
int data;
struct tree* right;
struct tree* left;
};
typedef struct tree* treeptr;
I'm implementing an binary search tree but for some reasons I 'm not able to add a node
my: input was :
a.value = 5;
add_bst_node(&t,a);
mystructures:
typedef struct BST_node{
entity value;
struct BST_node* left;
struct BST_node* right;
}BST_node;
typedef struct BST_tree{
BST_node* root;
}BST_tree;
my code for add a node:
void add_bst_node2(BST_node* root,entity* e){
if(!root){
root = (BST_node*)malloc(sizeof(BST_node));
root->value = *e;
root->left = NULL;
root->right = NULL;
return;
}
else if(great_than(&root->value,e))
add_bst_node2(root->left,e);
else
add_bst_node2(root->right,e);
}
void add_bst_node(BST_tree* t,entity e){
add_bst_node2(t->root,&e);
printf("%d\n",t->root==NULL);
}
Someone can explayn why I'can't add a node?
Apart from not passing double pointer to BST_node (i.e. BST_node**) in add_bst_node2() as noted in the comments, you also didn't implement the function properly.
Your implementation never really adds a node, but instead in enters into infinite recursion.
Here you can find some clean theory about BST - http://www.zentut.com/c-tutorial/c-binary-search-tree/
Here is an untested correction of your code. Note that here we pass pointer to BST_tree instead of BST_node
void add_bst_node2(BST_tree* tree,entity* e){
if(!tree->root){
/* If the binary search tree is empty, we just create a root node */
tree->root = bst_create_node(e);
return;
}
int is_left = 0;
BST_node* current_node = tree->root;
BST_node* prev = NULL;
/* Traverse the tree until we find the proper position for the new node.
* The position is denoted by 'current_node'
*/
while(current_node != NULL) {
prev = current_node;
if(greater_than(¤t_node->value, e)) {
is_left = 1;
current_node = current_node->left;
} else {
is_left = 0;
current_node = current_node->right;
}
}
/* We finally know the position where we should add the new node */
if(is_left)
prev->left = bst_create_node(e);
else
prev->right = bst_create_node(e);
}
We introduce another function for creating and initializing a node...
BST_node *bst_create_node(entity *e)
{
BST_node *n = malloc(sizeof(BST_node));
n->value = *e;
n->left = NULL;
n->right = NULL;
return n;
}
And finally we change add_bst_node()
void add_bst_node(BST_tree* t,entity e){
add_bst_node2(t, &e);
printf("%d\n", t->root==NULL);
}
From what it seems, a is a struct BST_node and value is a variable in it. You have to either pass the value to the function and handle the node creation there, or pass the whole constructed node and just point to it from the existing tree.
first thing is that you put an unnecessary structure BST_tree.You do it in simple way like
struct node
{
int value;
node* left;
node* right;
};
struct node* root;
I suggest you try with this code
struct node* insert(struct node* r, int data)
{
if(r==NULL) // BST is not created created
{
r = (struct node*) malloc(sizeof(struct node)); // create a new node
r->value = data; // insert data to new node
// make left and right childs empty
r->left = NULL;
r->right = NULL;
}
// if the data is less than node value then we must put this in left sub-tree
else if(data < r->value){
r->left = insert(r->left, data);
}
// else this will be in the right subtree
else {
r->right = insert(r->right, data);
}
return r;
}`
`
I try to implement a binary tree in C with only one operation for the moment - insertion of a node to the tree. The problem I am facing is that I have a segmentation fault. The problem comes from the function insert, in the root = leaf instruction but I can't figure out how can I fix it. I've tried to write the function in a slightly different way. Instead of passing a leaf, I tried to pass a value to the insert function and to create a node of the binary tree inside the insert function. It didn't work out.
Can you please me tell me where I am wrong in my code? Thank you
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
struct binaryTree
{
int data;
struct binaryTree *left;
struct binaryTree *right;
};
//the seg fault comes from the function insert
void insert(struct binaryTree *leaf,struct binaryTree *root)
{
if(root == NULL)
{
//this is the problematic instruction
root = leaf;//construct the tree if it has not been constructed before
root->left = NULL;
root->right = NULL;
}
else if(leaf->data > root->data)
{
insert(leaf, root->right);
}
else if(leaf->data < root->data)
insert(leaf,root->left);
else
{
printf("The element is in the tree already.\n");
}
}
void print(struct binaryTree *root)
{
printf("-------Print--------\n");
if(root == NULL) return;
print(root->left);
printf("%d\n", root->data);
print(root->right);
}
void createNode(int value,struct binaryTree *node)
{
printf("-------CreateNode--------\n");
node = malloc(sizeof(struct binaryTree));
node->data = value;
node->left = NULL;
node->right = NULL;
}
void destroy(struct binaryTree *root)
{
if(root != NULL)
{
destroy(root->right);
destroy(root->left);
free(root);
}
}
int main()
{
struct binaryTree *root = NULL,*a,*b,*c;
createNode(42,a);
createNode(13,b);
createNode(20,c);
insert(a,root);
insert(b,root);
insert(c,root);
print(root);
destroy(root);
return 0;
}
The problem:
At the beginning of main(), root is NULL and a is untitialised.
The problem is that createNode(42,a); will create and allocate a node, but it's address will be lost. Only the local parameter node will be set by this function and lost forever as soon as it returns. This value will not be copied to a, which hence remain unitialized.
Then you try to instert(a, root): a is still an unitialised pointer and root is still NULL. The first thing that will hapen in insert() is that you'll copy the unitialised pointer into root, and then you dereference this invalid pointer by trying to set some structure members to NULL. That causes the segmentation fault !
How to solve it:
Make sure that createNode() returns the value:
struct binaryTree *createNode(int value)
{
printf("-------CreateNode--------\n");
struct binaryTree *node = malloc(sizeof(struct binaryTree));
node->data = value;
node->left = NULL;
node->right = NULL;
return node;
}
and change min accordingly:
a = createNode (42);
...
You then have a similar problem in insert(), with the root argument. You could here do a similar technique, by rewriting your function:
struct binaryTree *insert(struct binaryTree *leaf,struct binaryTree *root) {...}
But it requries a little bit more gynmnastics as with createNode().
I propose you therefore another alternative, passing as argument a pointer to a root pointer: this pemits you to change the value of the root poniter
void insert(struct binaryTree *leaf,struct binaryTree **root) // pointer to pointer
{
if(*root == NULL)
{
//this is the problematic instruction
*root = leaf;//construct the tree if it has not been constructed before
(*root)->left = NULL;
(*root)->right = NULL;
}
else if(leaf->data > (*root)->data)
{
insert(leaf, &root->right);
}
else if(leaf->data < (*root)->data)
insert(leaf,&root->left);
else
{
printf("The element is in the tree already.\n");
}
}
In main you'd then call it:
insert(a,&root);
I am trying to build a huffman tree out of binary search tree. Sadly my code is crashing (Segmentation fault (core dumped)).
This is how the struct is defined:
struct Node
{
unsigned char m_ch;
int m_freq;
struct Node *m_ls,*m_rs;
struct Node *m_hls,*m_hrs;
};
delMin is passed a double pointer to a binary search tree, and deletes from it the leftmost leaf unless it reaches a Node with m_ch==0 and return the deleted Node
I can't find my mistake
struct Node *delMin(struct Node **root)
{
struct Node *current = *root;
struct Node *b4Current;
if (current == NULL)
return NULL;
while (current->m_ls != NULL)
{
if (current->m_ch == 0)
break;
b4Current = current;
current = current->m_ls;
}
if (current->m_ch == 0)
b4Current->m_ls = NULL;
else
{
if (b4Current == NULL)
*root = current->m_rs;
else
b4Current->m_ls = current->m_rs;
}
return current;
}
struct Node *huffman(struct Node *root)
{
struct Node *left;
struct Node *right;
struct Node *tempRoot;
struct Node *huffmanTree;
while (root->m_ch != 0)
{
left = delMin(&root);
right = delMin(&root);
tempRoot = createNode((left->m_freq) + (right->m_freq), 0);
tempRoot->m_hls = left;
tempRoot->m_hrs = right;
insertTree(&root, tempRoot);
}
huffmanTree = tempRoot;
return huffmanTree;
}
EDIT: Added code for the insertTree function called by Huffman
void insertTree(struct Node **root,struct Node *n)
{
if (!*root)
{
*root=n;
return;
}
if(n->m_freq<(*root)->m_freq)
{
insertTree(&((*root)->m_ls),n);
}
else
{
insertTree(&((*root)->m_rs),n);
}
}
In delMin this code section
if (current->m_ch == 0)
b4Current->m_ls = NULL;
else
{
if (b4Current == NULL)
*root = current->m_rs;
else
b4Current->m_ls = current->m_rs;
}
there is no guarantee that b4Current is not NULL.
Consider the case where the root node has m_ch == 0 and m_ls == NULL. You will take the if branch and dereference b4Current.
You need to initialize b4Current with NULL and check for it before any dereference.
You also need to ensure root itself is non-null before initializing current = *root in delMin or dereferencing it in huffman
These should all be initialized to NULL
struct Node *left;
struct Node *right;
struct Node *tempRoot;
struct Node *huffmanTree;
and it is possible, again, to never enter the while loop, leaving tempRoot unset causing a potential segFault in the caller of huffman when you return its value.