Program crashes when inserting a node in a binary tree - c

I created the following library to insert,delete,search and print nodes in a binary tree.
#include <stdlib.h>
struct NODE
{
int code;
char subject[20];
struct NODE *left;
struct NODE *right;
};
void InOrder(struct NODE *R)
{
if (R==NULL)
return;
InOrder(R->left);
printf("%d %s\n",R->code,R->subject);
InOrder(R->right);
}
void PreOrder(struct NODE *R)
{
if (R==NULL)
return;
printf("%d %s\n",R->code,R->subject);
InOrder(R->left);
InOrder(R->right);
}
void PostOrder(struct NODE *R)
{
if (R==NULL)
return;
InOrder(R->left);
InOrder(R->right);
printf("%d %s\n",R->code,R->subject);
}
struct NODE *Search(struct NODE *R,int CODE,struct NODE **father)
{
if(R==NULL)
return NULL;
if(R->code==CODE)
{
*father=R;
return R;
}
if (CODE<R->code)
return Search(R->left,CODE,father);
else
return Search(R->right,CODE,father);
}
struct NODE * CreateNode(struct NODE T)
{
struct NODE *tmp;
tmp=(struct NODE *)malloc(sizeof(T));
*tmp=T;
tmp->left=tmp->right=NULL;
return tmp;
}
int Insert(struct NODE **R,struct NODE ND)
{
struct NODE *cur,*fath=NULL;
cur=Search(*R,ND.code,&fath);
if (cur)
return 0;
cur=CreateNode(ND);
if(fath==NULL)
*R=cur;
else
if(fath->code>ND.code)
fath->left=cur;
else
fath->right=cur;
return 1;
}
struct NODE *MinOfMax (struct NODE *ND)
{
struct NODE *tmp;
if (ND==NULL)
return NULL;
if(ND->right==NULL)
return NULL;
tmp=ND->right;
while(tmp->left!=NULL)
tmp=tmp->left;
return tmp;
}
struct NODE* Delete(struct NODE *R, int code)
{
if (R==NULL)
return R;
if (code<R->code)
R->left=Delete(R->left,code);
else if (code>R->code)
R->right=Delete(R->right,code);
else
{
if (R->left==NULL)
{
struct NODE *temp=R->right;
free(R);
return temp;
}
else if (R->right==NULL)
{
struct NODE *temp=R->left;
free(R);
return temp;
}
struct NODE *temp=MinOfMax(R->right);
R->code=temp->code;
R->right=Delete(R->right,temp->code);
}
return R;
}
When i try to insert a node in the binary tree,the program crashes.Here is my main:
int main(int argc,char* argv[])
{
typedef struct NODE NODE;
NODE *root=NULL;
NODE tmp;
Insert(&root,tmp);
return 0;
}
I tried to assign static values (for example code=100 and subject="Physics") but still the program crashes.Should i malloc something,change anything in my header file or do something entirely different?I'm stuck here for hours without finding any solution.Most insert functions out there assume that i only have one integer as data in the node,but i need to pass the entire node.

Your code basically does nothing. It seems you copy-pasted it from somewhere. I tried to figure it out and here's a code example. Basically you've to initializate a new node in the main when you try to insert it.
Note that's just an example, i didn't a full test.
int main(int argc,char* argv[])
{
typedef struct NODE NODE;
NODE *root=NULL;
NODE *tmp = malloc(sizeof(struct NODE));
tmp->code = 1; /*Just a number*/
strcpy(tmp->subject,"prova"); /*Put something in it*/
Insert(&root,*tmp); /* Try to insert it*/
PreOrder(root); /*Try to see if it has been inserted*/
return 0;
}

Your tmp node, which is going to be the newly inserted node is used uninitialized in your main(). Your compiler could have warned you for this, if you had used -Wall flag.
So let's take a look in your insert function:
int Insert(struct NODE **R, struct NODE ND)
{
struct NODE *cur,*fath=NULL;
cur = Search(*R, ND.code, &fath); // ND.code is junk, since ND is uninitialized
...
return 1;
}
which likely causes the segmentation fault.
root is too, you could initialize it to NULL in main().
Not the cause of your problem, but Do I cast the result of malloc? No.

Related

Linked list in c returns negative number instead of adding node

Can someone explain to me why this code returns a random negative number instead of adding the node as it should? If the call to addnode is removed the main function works as it should so the problem lies with the addnode function. I don't think it's malloc that has the problem and I can't for the life of me figure out what is. Please help, I'm an amateur at c and I have a vague understanding of how pointers work so I guess something's wrong with my pointers. Here's the full code :
#include <stdio.h>
#include <stdlib.h>
struct node
{
int data;
struct node *next;
};
int addNode(struct node **head, int value);
void printList(struct node **head);
int main()
{
int value;
struct node *head;
head=NULL;
//int isempty(struct node *head);
for(int i=0;i<10;i++)
{
printf("\nInsert node value :");
scanf("%d",&value);
addNode(&head,value);
}
printList(&head);
return 0;
}
int addNode(struct node **head,int value)
{
struct node *newnode;
newnode=(struct node *) malloc(sizeof(struct node));
//if(newnode==NULL)
if(!newnode)
{
printf("Memory allocation error \n");
exit(0);
}
if(*head=NULL)
{
newnode->data=value;
newnode->next=NULL;
*head=newnode;
return 1;
}
else
{
struct node *current;
*current = **head;
while(current != NULL)
{
if(value<=(current->data)){
//περίπτωση 1ου κόμβου σε μη κενή λίστα
if(current==*head){
newnode->data=value;
newnode->next=*head;
*head=newnode;
return 1;
}
//περίπτωση ενδιάμεσου κόμβου
newnode->data=value;
return 1;
}
current = current->next;
}
}
}
/*int isempty(struct node *head){
return (head==NULL);
}*/
void printList(struct node **head) {
struct node *ptr = *head;
printf("\n[ ");
//start from the beginning
while(ptr != NULL) {
printf("(%d) ",ptr->data);
ptr = ptr->next;
}
printf(" ]");
return;
}
Well for starters you are having an assignment instead of a comparison in addNode
if(*head=NULL) should be if(*head==NULL)
Other than that, I think you are trying to maintain the elements in a sorted manner? But in any case you are manipulating pointers a bit more than you need to.

How can I change where a node points inside a function

I want to create a function that search for a certain value in a linked list and then put the node containing it and the node before the one containing it in two separate nodes.
This is my code and I can't figure out why it does not work:
#include <stdio.h>
#include <stdlib.h>
struct node{
int val;
struct node* next;
};
typedef struct node node_t;
void printlist(node_t *head){
node_t *temp=head;
while (temp!=NULL){
printf("%d -",temp->val);
temp=temp->next;
}
printf("\n");
}
node_t *create_new_node(int value){
node_t *result=malloc(sizeof(node_t));
result->val=value;
result->next=NULL;
return result;
}
void *insert_after_node(node_t *node_to_insert,node_t *newnode){
newnode->next=node_to_insert->next;
node_to_insert->next=newnode;
}
void *find_node(node_t *head,int value,node_t *R,node_t *RA){
node_t *tmp=head;
while (R!=NULL && tmp!=NULL){
if (tmp->val==value)
R=tmp;
else{
RA=tmp;
tmp=tmp->next;
}
}
}
int main(){
node_t *head=NULL;
node_t *tmp;
node_t *R=NULL;
node_t *RA=NULL;
for (int i=0;i<25;i++){
tmp=create_new_node(i);
insert_at_head(&head,tmp);
}
find_node(head,13,R,RA);
printlist(head);
printlist(RA);
printlist(R);
}
Thank you !
You want to pass in the addresses of R and RA to find_node. And declare the params as **
void *find_node(node_t *head,int value,node_t **R,node_t **RA){
and then use (*R/ *RA) in the function
Call with
find_node(head,13,&R,&RA);
In your version, find_node cannot reassign the pointers passed in.

Problem in linked list while using struct variable

Code for linked list using memory allocation:
#include<stdio.h>
struct node
{
int val;
struct node *point;
};
int main()
{
struct node *head;
head=(struct node* ) malloc(sizeof(struct node ));
void create(struct node* start);
void print(struct node* start);
create(head);
print(head);
return 0;
}
void create(struct node* start)
{
int test,a=1;
struct node* cur;
cur=start;
while(scanf("%d",&test)!=EOF)
{ if(a!=1)
{
cur=cur->point;
}
cur->point=(struct node* ) malloc(sizeof(struct node ));
cur->val=test;
a++;
printf("---------------");
printf("%d\n",cur);
printf("%d\n",cur->val);
printf("%d\n",cur->point);
printf("%d\n",a);
printf("---------------");
}
cur->point=NULL;
return;
}
void print(struct node* start)
{
struct node* cur;
cur=start;
while(cur!=NULL)
{
printf("%d ",cur->val);
cur=cur->point;
}
return;
}
Code for linked list using struct variable:
#include<stdio.h>
struct node
{
int val;
struct node *point;
};
int main()
{
struct node *head,link;
head=&link;
void create(struct node* start);
void print(struct node* start);
create(head);
print(head);
return 0;
}
void create(struct node* start)
{
int test,a=1;
struct node* cur;
cur=start;
while(scanf("%d",&test)!=EOF)
{ if(a!=1)
{
cur=cur->point;
}
struct node link;
cur->point=&link;
cur->val=test;
a++;
printf("---------------");
printf("%d\n",cur);
printf("%d\n",cur->val);
printf("%d\n",cur->point);
printf("%d\n",&link);
printf("%d\n",a);
printf("---------------");
}
cur->point=NULL;
return;
}
void print(struct node* start)
{
struct node* cur;
cur=start;
while(cur!=NULL)
{
printf("%d ",cur->val);
cur=cur->point;
}
return;
}
When I use 2nd code it doesn't work correctly. It prints just two values.
In while loop of create() I use struct node type variable declaration.
That's why it should it would declare a new struct node type link variable and a new memory (struct node link) address should be seen in every execution.
So what's the problem?
I am a newbie learning data structure using C. Please explain in simple language.

Tree structure segmentation fault

Segmentation fault (core dumped), please help. I don't understand what I did wrong. The code compiles but I get the error above. I understand that the code tries to access memory that it can't, but I don't see where it is happening.
#include <stdio.h>
#include <stdlib.h>
int freq[256] = {0};
struct Node
{
unsigned char m_ch;
int m_freq;
struct Node *m_ls,*m_rs;
struct Node *m_hls,*m_hrs;
};
struct Node* createNode(int freq,char ch);
void insertTree(struct Node **root,struct Node * n);
struct Node* getBinTree(FILE *fsrc);
void inorder(struct Node *root);
int main()
{
FILE *fsrc;
struct Node *tree=NULL;
fsrc = fopen("src.txt","rb");
tree=getBinTree(fsrc);
inorder(tree);
return 1;
}
struct Node* createNode(int freq,char ch)
{
struct Node *pNode=NULL;
pNode->m_freq=freq;
pNode->m_ch=ch;
return pNode;
}
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);
}
}
struct Node* getBinTree(FILE *fsrc)
{
struct Node *temp=NULL;
struct Node **root=NULL;
int c,i;
while ((c = fgetc(fsrc)) != EOF)
{
freq[c]++;
}
freq[255]=1;
fclose(fsrc);
for(i=0;i<256;i++)
{
if(freq[i]>0)
{
temp=createNode(freq[i],i);
insertTree(root,temp);
}
}
}
void inorder(struct Node *root)
{
if(root != NULL)
{
inorder(root->m_ls);
printf(" %d\n",root->m_freq);
inorder(root->m_rs);
}
return;
}
struct Node *pNode=NULL;
pNode->m_freq=freq;
One of the reasons is dereferencing the NULL pointer in the quoted code block above.
Memory must be allocated before using the pointer. Like this:
struct Node *pNode = malloc (sizeof *pNode);

BST insert operation. don't insert a node if a duplicate exists already

the following code reads an input array, and constructs a BST from it. if the current arr[i] is a duplicate, of a node in the tree, then arr[i] is discarded. count in the struct node refers to the number of times a number appears in the array. fi refers to the first index of the element found in the array. after the insertion, i am doing a post-order traversal of the tree and printing the data, count and index (in this order). the output i am getting when i run this code is:
0 0 7
0 0 6
thank you for your help.
Jeev
struct node{
int data;
struct node *left;
struct node *right;
int fi;
int count;
};
struct node* binSearchTree(int arr[], int size);
int setdata(struct node**node, int data, int index);
void insert(int data, struct node **root, int index);
void sortOnCount(struct node* root);
void main(){
int arr[] = {2,5,2,8,5,6,8,8};
int size = sizeof(arr)/sizeof(arr[0]);
struct node* temp = binSearchTree(arr, size);
sortOnCount(temp);
}
struct node* binSearchTree(int arr[], int size){
struct node* root = (struct node*)malloc(sizeof(struct node));
if(!setdata(&root, arr[0], 0))
fprintf(stderr, "root couldn't be initialized");
int i = 1;
for(;i<size;i++){
insert(arr[i], &root, i);
}
return root;
}
int setdata(struct node** nod, int data, int index){
if(*nod!=NULL){
(*nod)->fi = index;
(*nod)->left = NULL;
(*nod)->right = NULL;
return 1;
}
return 0;
}
void insert(int data, struct node **root, int index){
struct node* new = (struct node*)malloc(sizeof(struct node));
setdata(&new, data, index);
struct node** temp = root;
while(1){
if(data<=(*temp)->data){
if((*temp)->left!=NULL)
*temp=(*temp)->left;
else{
(*temp)->left = new;
break;
}
}
else if(data>(*temp)->data){
if((*temp)->right!=NULL)
*temp=(*temp)->right;
else{
(*temp)->right = new;
break;
}
}
else{
(*temp)->count++;
free(new);
break;
}
}
}
void sortOnCount(struct node* root){
if(root!=NULL){
sortOnCount(root->left);
sortOnCount(root->right);
printf("%d %d %d\n", (root)->data, (root)->count, (root)->fi);
}
}
Well, for one, you're passing a pointer to a pointer in your insert function:
void insert(int data, struct node **root, int index);
And then you have a temporary variable:
struct node** temp = root;
that you use to traverse your tree. When you do that, you're changing your root. Just pass a pointer, i.e.,
void insert(int data, node *root , int index){
Second, if(data<=(*temp)->data){ should JUST be <, not <=.
Hint: in general, it's fairly rare when you actually need to pass a pointer to a pointer.
put an if condition in while loop of insert function.
while(1)
{
if(data==(*temp)->data)
break;
else
{
your stuff;
}
}
It may your answer.

Resources