Segmentation fault upon insertion into binary search tree - c

I wrote the following code to insert into binary search tree which can have duplicate entries but i get segmentation fault for larger inputs like greater than 30 ....plz help!! The duplicate entries are stored in the right branch of the node
#include<stdio.h>
#include<time.h>
#include<stdlib.h>
typedef struct vertex{
int num;
struct vertex* r;
struct vertex* l;
} node;
void insert(node* T,int x)
{
if(x < T->num)
{
if(T->l == NULL)
{
T->l = (node*)malloc(sizeof(node));
T->l->num = x;
printf("%4d ",x);
return;
}
else
{
insert(T->l,x);
}
}
else if(x >= T->num)
{
if(x == T -> num)
if(T->r == NULL)
{
T->r = (node*)malloc(sizeof(node));
T->r->num = x;
printf("%4d ",x);
return;
}
else
insert(T->r,x);
}
}
main()
{
srand((unsigned int)time(NULL));
int i,n,m,x;
node* T;
printf("n = ");
scanf("%d",&n);
printf("\nm = ",&m);
scanf("%d",&m);
printf("\n\n\n+++ Inserting %d random integers between 1 and %d\n",n,m);
x = 1 + rand() % m;
T = (node*)malloc(sizeof(node));
T->num = x;
printf("%4d (1)",x);
for(i=1;i<n;i++)
{
x = 1+rand() % m;
insert(T,x);
if(i%8 == 7)
printf("\n");
}
printf("\n\n");
}

malloc() does not initialize memory, so set other member to NULL after allocation or use calloc(). Without this you will be accessing random memory when you do T->l or T->r.
T = malloc(sizeof(node));
T->num = x;
T->l = NULL;
T->r = NULL;
or
T = calloc(1, sizeof(node));
T->num = x;
Do this in all places where you use malloc()

malloc(noofbytes) function only allocate noofbytes space only does not initialize with NULL .
This is the problem with your code.
When you allocate memory
T->l = (node*)malloc(sizeof(node));
T->l->num = x;
you allocated memory of size of structure node but it is not initialized . Means
T->l->l and T->l->r is not NULL and have some garbage value.
when you traverse it T->l== NULL or T->r==NULL condition not get satisfied and so it gives segmentation fault.

Related

Run time error on C that I am unable to detect

My program inputs a sequence of elements and checks if a up to down sequence of the same numbers exists in a binary tree.
To be clear, I am submitting my answer to a system set up by my professor that just responds with a Failed - run time error, with no other details. When I compile and run it on Xcode, it works perfectly fine with no run time errors. I have checked for divide by zero, memory leakage, array out of bounds etc but I can't seem to spot the error. For this reason my code will be a bit lengthy because I can't figure out the problematic part.
node *n;
node *newNode(int data)
{
node *new_node = (node *)malloc(sizeof(node));
new_node->number = data;
new_node->left = NULL;
new_node->right = NULL;
return new_node;
}
node *insert(int arr2[], node *ptr, int i, int M2, int x)
{
if (i < M2)
{
node *temp = newNode(arr2[i]);
ptr = temp;
if (ptr -> number == x)
n = ptr; // n is a global variable of type node*
ptr->left = insert(arr2, ptr->left, 2 * i + 1, M2, x);
ptr->right = insert(arr2, ptr->right, 2 * i + 2, M2, x);
}
return ptr;
}
void checkPath(int arr1[], node *ptr, int *i, int M1)
{
node *temp = (node *)malloc(sizeof(node));
if (n == NULL)
return;
while ((*i) < M1)
{
if (n->left->number == arr1[*i])
{
(*i)++;
temp = n->left;
n = temp;
}
else if(n->right->number == arr1[*i])
{
(*i)++;
temp = n -> right;
n = temp;
}
else
break;
}
}
int main()
{
int N, M1, M2, z;
scanf("%d", &N);
for (int i = 0; i < N; i++)
{
z = 1;
scanf("%d", &M1);
int arr1[M1];
for (int j = 0; j < M1; j++)
scanf("%d", &arr1[j]);
scanf("%d", &M2);
int arr2[M2];
for (int k = 0; k < M2; k++)
scanf("%d", &arr2[k]);
node *ptr = (node *)malloc(sizeof(node));
ptr = insert(arr2, ptr, 0, M2, arr1[0]);
checkPath(arr1, ptr, &z, M1);
if (z == M1)
printf("True\n");
else
printf("False\n");
free(ptr);
}
return 0;
}
Sorry for the lengthy piece of code. Thanks in advance!
At least this problem: lost memory.
checkPath() never uses the result of malloc(). This suggest a logical error in this function.
void checkPath(int arr1[], node *ptr, int *i, int M1)
{
node *temp = (node*) malloc(sizeof(node));
...
while((*i) < M1)
...
temp = n -> left;
n = temp;
...
temp = n -> right;
n = temp;
...
}
}
It is concerning code is reading and setting a global variable n here.
This may or may not be a key problem.
What about input data? Is it guaranteed to be OK or not?
There is no validation at data input in the code.
Well, I've just reproduced the failure:
./test
2
1
1
1
1
True
2
2
2
2
2
2
Segmentation fault (core dumped)
Given that 'node' is this:
typedef struct _node
{
int number;
struct _node *left;
struct _node *right;
} node;
But the actual error in logic I didn't find yet.
BTW the logic is somewhat curious.
P.S. this input would also give a crash:
./test
2
2
2
2
2
2
2
2
Segmentation fault (core dumped)
Consider adding pointer checks before accessing 'left' or 'right'
if (n->left && n->left->number == arr1[*i])
and
else if(n->right && n->right->number == arr1[*i])

Connected Components in an undirected graph - Algorithm fhor StackOverflow users (Segmentation fault)

In response to my first question on the subject, I found (pg 89)/ built an algorithm that prints the connected components. However, for an input of the type
6 edges
4 vertices
2 3
2 3
4 5
0 1
the program returns a segmentation error. Why?
#include<stdlib.h>
#define MAXVERTICES 100
void enqueue(int);
int deque();
int isConnected(char **graph,int noOfVertices);
void BFS(char **graph,int vertex,int noOfVertices);
int count = 0;
struct node{
int v;
struct node *next;
};
typedef struct node Node;
typedef struct node *Nodeptr;
Nodeptr Qfront = NULL;
Nodeptr Qrear = NULL;
char *visited;//array that keeps track of visited vertices.
void enqueue(int vertex){
if(Qfront == NULL){
Qfront = malloc(sizeof(Node));
Qfront->v = vertex;
Qfront->next = NULL;
Qrear = Qfront;
}
else{
Nodeptr newNode = malloc(sizeof(Node));
newNode->v = vertex;
newNode->next = NULL;
Qrear->next = newNode;
Qrear = newNode;
}
}
int deque(){
if(Qfront == NULL){
printf("Q is empty , returning -1\n");
return -1;
}
else{
int v = Qfront->v;
Nodeptr temp= Qfront;
if(Qfront == Qrear){
Qfront = Qfront->next;
Qrear = NULL;
}
else
Qfront = Qfront->next;
free(temp);
return v;
}
}
int isConnected(char **graph,int noOfVertices){
int i;
BFS(graph,0,noOfVertices);
for(i = 0;i < noOfVertices;++i)
if(visited[i] == 'N')
return 0;
return 1;
}
void BFS(char **graph,int v,int noOfVertices){
int i,vertex;
visited[v] = 'Y';
enqueue(v);
while((vertex = deque()) != -1){
//printf("\nConnected component %d\n",++count);
//printf("%d ",vertex+1);
for(i = 0;i < noOfVertices;++i)
if(graph[vertex][i] == 1 && visited[i] == 'N'){
enqueue(i);
visited[i] = 'Y';
}
}
}
void listConnectedComponents(char **graph,int noOfVertices){
int i;
for(i = 0;i < noOfVertices;++i){
if(visited[i] == 'N')
BFS(graph,i,noOfVertices);
}
}
int main(){
int n,e;//n is number of vertices, e is number of edges.
int i,j;
char **graph;//adjacency matrix
printf("Enter number of vertices:");
scanf("%d",&n);
if(n < 0 || n > MAXVERTICES){
fprintf(stderr, "Please enter a valid positive integer from 1 to %d",MAXVERTICES);
return -1;
}
graph = malloc(n * sizeof(char *));
visited = malloc(n*sizeof(char));
for(i = 0;i < n;++i){
graph[i] = malloc(n*sizeof(int));
visited[i] = 'N';//initially all vertices are not visited.
for(j = 0;j < n;++j)
graph[i][j] = 0;
}
printf("enter number of edges and then enter them in pairs:");
scanf("%d",&e);
for(i = 0;i < e;++i){
int u,v;
scanf("%d%d",&u,&v);
graph[u-1][v-1] = 1;
graph[v-1][u-1] = 1;
}
if(isConnected(graph,n))
printf("The graph is connected");
else printf("The graph is NOT connected\n");
}
I believe it is due to the positions allocated in the adjacency matrix.

Sum of elements on the way to largest leaf in BST

I am trying to sum all the nodes on the way to the largest leaf in a binary search tree. The nodes contain only positive numbers.
#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;
} 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;
return w;
}
if (k <= t->key)
t->left = InsertBST(t->left, k);
else
t->right = InsertBST(t->right, k);
return t;
}
int SumMaxOfBST(Tree* t, int *sum_max)
{
if (t == NULL) {
*sum_max = -1;
return *sum_max;
}
if (t->right == NULL) {
*sum_max += t->key;
return *sum_max;
}
*sum_max += t->key;
*sum_max += SumMaxOfBST(t->right, sum_max);
return *sum_max;
}
int main()
{
int i;
srand (time(NULL));
Tree* t = NULL;
for (i = 0; i < 20; i++)
t = InsertBST(t, rand() % 1000);
int sum_way = 0;
int a = SumMaxOfBST(t, sum_way);
printf("Sum on the way to the largest leaf %d:\n", a);
return 0;
}
This exits with non-zero status. My strong suspicion is that I have botched the use of pointers, however, after several rewrites and videos on the use of pointers I still don't seem to grasp what's going on. If I understand correctly,*sum_max += x should increment the value of sum_max by x. At which point is my use of pointers off?
I don't get why you take a pointer to int as a paramter for SumMaxOfBST, I think the function written like this is simpler.
int SumMaxOfBST(Tree* t)
{
if (t == NULL) {
return 0;
}
if (t->right == NULL) {
return t->key;
}
return t->+key + SumMaxOfBST(t->right);
}
Furthermore in your main, you're passing sum_way that is an int, while SumMaxOfBST expects an int*. You should pass &sum_way instead.

Access violation reading location 0xCDCDCDCD

As the title states, I'm getting an error
Access violation reading location 0xCDCDCDCD.
Now I'm dealing with an array of linked lists, and I believe the trouble to be something around adding to the linked list. I'm fine with this usually, but I feel I'm doing something wrong with memory allocation.
Here are my structs:
Graph:
typedef struct graph
{
int V;
int *state;
EdgeList *edges;
} Graph;
Edge:
typedef struct edge
{
int toVertex;
int weight;
} Edge;
EdgeList:
typedef struct edgeNode
{
Edge edge;
struct edgeNode *next;
} *EdgeList;
Here is the main function that runs it all:
main()
{
Graph myGraph;
scanf("%d", &(myGraph.V));
myGraph.state = (int)malloc(myGraph.V*sizeof(int));
myGraph.edges = (EdgeList*)malloc(myGraph.V*sizeof(EdgeList));
int *inDegrees;
inDegrees = (int)malloc(sizeof(int)*myGraph.V);
/* Sets all array values to 0 */
for (int counter = 0; counter < myGraph.V; counter++)
{
inDegrees[counter] = 0;
}
for (int i = 0; i < myGraph.V; i++)
{
int number_of_edges;
int input = 0; /*For that little experimental bit*/
scanf("%d", &(myGraph.state[i]));
scanf("%d", &number_of_edges);
if (number_of_edges > 0)
{
for (int j = 0; j < number_of_edges; j++)
{
Edge newEdge;
scanf("%d,%d", &(newEdge.toVertex), &(newEdge.weight));
inDegrees[newEdge.toVertex]++;
printf("%s%d\n", "\nOoh, new input for ", newEdge.toVertex);
/*insert at front*/
EdgeList newNode = (EdgeList)malloc(sizeof (struct edgeNode));
newNode->edge = newEdge;
newNode->next = myGraph.edges[i];
myGraph.edges[i] = newNode;
/* Bit to calculate state.*/
EdgeList current = myGraph.edges[i];
while (current != NULL)
{
if (current->edge.toVertex == i)
{
input += (current->edge.weight)*(myGraph.state[i]);
}
current = current->next;
}
}
if (input > 0)
{
myGraph.state[i] = 1;
}
else
{
myGraph.state[i] = 0;
}
}
}
//print
for (int k = 0; k < myGraph.V; k++)
{
printf("\n%s%d%s", "In degrees for ", k, ": ");
printf("%d", inDegrees[k]);
}
}
In particular, the error comes during the traversal of the linked list. It's in the above code, but I'll highlight it here:
EdgeList current = myGraph.edges[i];
while (current != NULL)
{
if (current->edge.toVertex == i)
{
input += (current->edge.weight)*(myGraph.state[i]);
}
current = current->next;
}
If anyone can help, it'd be greatly appreciated because I'm rather stuck.
An value in uninitialized buffer allocated via malloc() is assigned to newNode->edge in newNode->next = myGraph.edges[i];.
The newNode is set to current via myGraph.edges[i] = newNode; and EdgeList current = myGraph.edges[i];.
Assuming that malloc() succeeded, current isn't NULL here, so it is entering the loop.
The uninitialized value assinged in 1 is assigned to current in current = current->next;.
An undefined behavior is invoked by using value in buffer allocated via malloc() and uninitialized at current != NULL.
To fix this error, initialize myGraph.edges in, for example, this way:
myGraph.edges = (EdgeList*)malloc(myGraph.V*sizeof(EdgeList));
for (int i = 0; i < myGraph.V; i++)
{
myGraph.edges[i] = NULL;
}
Also, remove the harmful casts to int of the pointer returned from malloc(). Casting the return values to pointers explicitly is also not considered as good.

Printing the nodes of a tree

I have a k-ary tree represented like that:
struct node {
int num;
int data;
struct node **kids;
}
I have created a function in order to print the data of the nodes of the tree.
Example:
a
/ | \
b c d
/
e
will print:
a
b
e
c
d
The function is:
void visit(struct node *head){
int i;
if (head == NULL)
return;
printf("%d\n", head->data);
for (i = 0; i < head->num; i++)
visit(head->kids[i]);
}
Question is, how can I also print the level of each node that i print. I tried to declare a variable int level = 0; and increment it but it won't work because the recursive call resets it.
void visit(struct node *head){
static int i;
if (head == NULL)
return;
printf("%d\n", head->data);
printf("Level : %d\n",i);
for (i = 0; i < head->num; i++)
visit(head->kids[i]);
i = i + 1;
}
Pass another parameter to recursive function
void visit(struct node *head, int level){
int i;
if (head == NULL)
return;
printf("%d : %d\n",level, head->data);
for (i = 0; i < head->num; i++)
visit(head->kids[i], level + 1);
}
And first time, invoke the function by passing level as zero.

Resources