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])
Related
so i've been working on a small function(part of a bigger program) that basically does the following:
define a list and the number of elements N, then input N elements. after this, input a value X;
I have to 'split' / re-order the list in a way so that its elements with value < X are in the beginning, in their relative order and the ones with higher value than X come after; eg.:
Input:
list 6
2 5 6 4 3 1
X 3
Output:
2 3 1 5 6 4
my code and list structure are down below:
(the partition function is at the bottom, just above the main function)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_STRING_SIZE 64
typedef struct ll_node_t
{
void* data;
struct ll_node_t* next;
} ll_node_t;
typedef struct linked_list_t
{
ll_node_t* head;
unsigned int data_size;
unsigned int size;
} linked_list_t;
linked_list_t*
ll_create(unsigned int data_size)
{
linked_list_t* list = malloc(sizeof(list));
// err handle
list->head = NULL;
list->data_size = data_size;
list->size = 0;
return list;
}
void
ll_add_nth_node(linked_list_t* list, unsigned int n, const void* new_data)
{
if(n < 0) exit(0);
ll_node_t* new_node = malloc(sizeof(ll_node_t*));
new_node->data = malloc(list->data_size);
// err handle
memcpy(new_node->data, new_data, list->data_size);
if(n == 0 || list->size == 0) {
new_node->next = list->head;
list->head = new_node;
list->size++;
return;
}
if(n < list->size)
{
ll_node_t* current = list->head;
for(int i = 0; i < n - 1; i++)
{
current = current->next;
}
new_node->next = current->next;
current->next = new_node;
list->size++;
return;
}
if(n >= list->size)
{
ll_node_t* current = list->head;
for(unsigned int i = 0; i < list->size - 1; i++)
{
current = current->next;
}
new_node->next = current->next;
current->next = new_node;
list->size++;
return;
}
}
ll_node_t*
ll_remove_nth_node(linked_list_t* list, unsigned int n)
{
if(n < 0) exit(0);
ll_node_t* removedNode = NULL;
if(n == 0)
{
removedNode = list->head;
list->head = list->head->next;
list->size--;
return removedNode;
}
if(n < list->size)
{
ll_node_t* current = list->head;
// err handle
for(int i = 0; i < n - 1; i++)
{
current = current->next;
}
removedNode = current->next;
current->next = current->next->next;
list->size--;
return removedNode;
}
if(n >= list->size)
{
ll_node_t* current = list->head;
// err handle
for(int i = 0; i < n - 1; i++)
{
current = current->next;
}
removedNode = current->next;
current->next = NULL;
list->size--;
return removedNode;
}
}
unsigned int
ll_get_size(linked_list_t* list)
{
return list->size;
}
void
ll_free(linked_list_t** pp_list)
{
ll_node_t* current = (*pp_list)->head;
for(int i = 0; i < (*pp_list)->size; i++)
{
(*pp_list)->head = current->next;
free(current->data);
free(current);
current = (*pp_list)->head;
}
free(*pp_list);
}
void
ll_print_int(linked_list_t* list)
{
if(!list->size) exit(0);
ll_node_t* current = list->head;
for(int i = 0; i < list->size; i++)
{
printf("%d ", *(int*)current->data);
current = current->next;
}
printf("\n");
}
void
ll_print_string(linked_list_t* list)
{
if(!list->size) exit(0);
ll_node_t* current = list->head;
for(int i = 0; i < list->size; i++)
{
printf("%s ", (char*)current->data);
current = current->next;
}
printf("\n");
}
void partition(linked_list_t* list, int x)
{
ll_node_t* current = list->head;
ll_node_t* tail = list->head;
for(int i = 0; i < list->size; i++)
{
tail = tail->next;
}
//special case for the first element of the list
if(*(int*)current->data > x)
{
tail->next = current;
list->head = current->next;
tail = current;
}
// loop that finds elements > X
for(int i = 0; i < list->size - 1; i++)
{
if(*(int*)current->data > x)
{
// assigning the element to the end
tail->next = current->next;
// linking the previous element to the one after the element
current->next = current->next->next;
tail = tail->next;
tail->next = NULL;
// moving on to next element
current = current->next;
}
else current = current->next;
// moving on to next element
}
}
int main()
{
linked_list_t* linkedList;
while (1) {
char command[16];
long size, num;
scanf("%s", command);
if (strcmp(command, "list") == 0) {
linkedList = ll_create(sizeof(int));
scanf("%ld", &size);
long int curr_nr;
for (int i = 0; i < size; ++i) {
scanf("%ld", &curr_nr);
ll_add_nth_node(linkedList, size, &curr_nr);
}
}
if (strcmp(command, "X") == 0) {
scanf("%ld", &num);
partition(linkedList, num);
ll_print_int(linkedList);
break;
}
}
ll_free(&linkedList);
return 0;
}
so since i have list size as well, which is the number of elements in the list i thought the following:
before looping through the list, check if the head(first element) needs to be shifted at the end (if > X) and then have a loop that loops list->size - 1 times and when the condition inside is met, do the following:
it'd basically loop through elements and look at their next's, so when an element's next is > X, it would be shifted:
assign the tail's next element to be the element > X(current->next), then link current elements next to the one after the element. after that the new tail would be the element that was added at the end.
currently I get a Segmentation fault at the first line inside the condition in the for loop, on this line:
tail->next = current->next;
disclaimer: the main program, as i've tested it, works just fine for adding elements, and so on.
I going to offer an answer that is not exactly a solution to your existing code, but instead presents a different way of thinking about organizing your data as you work through it.
What if, instead of trying to reorder the list in place (managing head, current, and tail) while iterating through it, we deconstruct the list and construct two new lists? Our result becomes the concatenation of these two lists.
Visualized in pseudocode this would work like:
Q is [2 5 6 4 3 1]
part Q <= 3
L is []
R is []
Q eql [2 5 6 4 3 1]
^ -> L eql [2]
Q eql [5 6 4 3 1]
^ -> R eql [5]
Q eql [6 4 3 1]
^ -> R eql [5 6]
Q eql [4 3 1]
^ -> R eql [5 6 4]
Q eql [3 1]
^ -> L eql [2 3]
Q eql [1]
^ -> L eql [2 3 1]
Q eql []
Q is L concat R
Q eql [2 3 1 5 6 4]
By doing this, our partitioning function gets utilize the same logic we used to build our list in the first place.
Here is an example of what this might look like in C, using a very simple linked list:
#include <stdio.h>
#include <stdlib.h>
typedef struct node {
struct node *next;
int value;
} node;
typedef struct {
node *head;
} list;
void list_append_node(list *l, node *n) {
node *root = l->head;
if (root) {
while (root->next)
root = root->next;
root->next = n;
} else
l->head = n;
}
void list_append_value(list *l, int v) {
node *n = calloc(1, sizeof *n);
n->value = v;
list_append_node(l, n);
}
void list_part(list *l, int v) {
list lower = { 0 };
list upper = { 0 };
for (node *curr = l->head, *temp; curr; curr = temp) {
temp = curr->next;
curr->next = NULL;
list_append_node(curr->value <= v ? &lower : &upper, curr);
}
list_append_node(&lower, upper.head);
l->head = lower.head;
}
int main(void) {
int inputs[] = { 2, 5, 6, 4, 3, 1 };
size_t len = sizeof inputs / sizeof *inputs;
list l = { 0 };
for (size_t i = 0; i < len; i++)
list_append_value(&l, inputs[i]);
list_part(&l, 3);
for (node *n = l.head, *t; n; n = t) {
t = n->next;
printf("%d ", n->value);
free(n);
}
putchar('\n');
}
stdout:
2 3 1 5 6 4
Note, the use of a node *tail member for each list could be implemented to improve the performance of list_append_node from O(N) to O(1).
I'm trying to make an implementation of merge() given 2 sorted linked lists, and output a linked list that merges the two and is sorted. I first create an array and put the items there, but when I print the array elements I get garbage values/seg fault. I know it's a lot of code to go through but I'd really appreciate anyone who can help :)
typedef struct _node {
int data;
struct _node * next;
} node_t;
typedef struct {
node_t * head;
node_t * tail;
} LL_t;
LL_t* createList(int num_nodes);
void printList(LL_t* L);
void merge(LL_t * L, LL_t * L2);
void merge(LL_t * L, LL_t * L2){
if(L2->head==NULL){ // empty L2
free(L2);
return;
}
else if(L->head==NULL){ // empty L1
*L=*L2;
free(L2);
return;
}
node_t* node=L->head;
int mid=0;
if(node->next!=NULL){
for (mid=0; node->next!=NULL; mid++) //finds last index of L1
node=node->next;
}
L->tail->next=L2->head;
L->tail=L2->tail;
node_t* ind = L->head;
free(L2);
int len=0;
for (len=0; ind!=NULL; len++) // finds num of items in list
ind=ind->next;
int arr[len];
int newarr[len];
node_t* cur= L->head;
for(int i=0; cur!=NULL; i++){ // creates array with list items
arr[i]=cur->data;
cur=cur->next;
}
int first=0;
int last=len;
int leftpos=0;
int rightpos=mid+1;
int newpos=0;
// insert elements to arr until a half of the array
// reaches mid or last
while(leftpos<=mid && rightpos<=last-1){
if(arr[leftpos]<arr[rightpos]){
newarr[newpos++]=arr[leftpos++];
}
else
newarr[newpos++]=arr[rightpos++];
}
// fills in the rest of the array
while(leftpos<=mid)
newarr[newpos++]=arr[leftpos++];
while(rightpos<=last)
newarr[newpos++]=arr[leftpos++];
for(int j=0; j<len; j++)
printf("newarr=%d\n",newarr[j]);
}
int main(void){
int num_nodes = 4;
int num_nodes2 = 3;
LL_t* L=createList(num_nodes);
LL_t* L2=createList(num_nodes2);
merge(L, L2);
}
// Creates the list. No problem here
LL_t* createList(int num_nodes){
LL_t* L = malloc(sizeof(LL_t));
L->head=NULL;
L->tail=NULL;
node_t *n;
int i=0;
for (i = 0; i < num_nodes; i++) {
n = malloc(sizeof(*n));
scanf("%d",&n->data);
n->next = NULL;
if (L->head == NULL){
L->head = n;
L->tail = n;
}
else {
L->tail->next = n;
L->tail = n;
}
}
puts("\n");
return L;
}
The problem is here in the merge():
while(rightpos<=last)
newarr[newpos++]=arr[leftpos++];
^^^^^^^
Here, the condition of while loop is rightpos<=last but accessing leftpos index element of arr and incrementing it. And if rightpos is less than last then the while loop condition will always be true which makes it an infinite loop. Every iteration of while loop is incrementing leftpos, at one stage its value will be greater than the size of array arr and accessing the array element beyond the size of the array is undefined behavior which includes program may give segmentation fault. It should be:
while(rightpos<=last)
newarr[newpos++]=arr[rightpos++];
I am trying to sort a linked list using bubble sort.But it gives segmentation problem
My logic to do so is below:
Note: Please note that i have to use only pass by reference every where (no return and global declaration for nodes)
void bubble_sort(node * * List, int size)
{
int i, j, temp;
node * first;
node * second;
node * final;
final=*List
for (i = 0; i < size - 1; i++)
{
first =final;
second = first -> link;
for (j = 0; j < size; j++)
{
if (first -> data < second -> data)
{
temp = first -> data;
first -> data = second -> data;
second -> data = temp;
}
first = first -> link;
}
} * List = first;
}
It's function call is :
bubble_sort(&start,val);
Could any one please help me in correcting the logic ?
EDIT: My full code:
#include <stdio.h>
//#include <conio.h>
#include <malloc.h>
/* structure containing a data part and link part */
struct node
{
int data;
struct node * link;
};
typedef struct node node;
node * start, * visit, * newnode;
//start=NULL
///////////////////////////////// Function declaration ///////////////////
void append(node * * q, int num);
void displaylist(node * start);
void bubble_sort(node * * List, int val);
//////////////////////////////////////////////////////////////////////////////////////////
void append(node * * q, int num)
{
node * temp, * temp2;
temp = * q;
//temp= (node* )malloc(sizeof (node));
if (temp == NULL) /* if the list is empty, create first node */
{
temp = (node * ) malloc(sizeof(struct node)); * q = temp;
} else
{
temp2 = * q;
while (temp2 -> link != NULL)
{
temp2 = temp2 -> link;
}
temp = (node * ) malloc(sizeof(struct node));
temp2 -> link = temp;
}
temp -> data = num;
temp -> link = NULL;
}
///////////////////////////////////////////////////////////////////////
void displaylist(node * start)
{
visit = start;
/* traverse the entire linked list */
while (visit != NULL)
{
printf("%d ", visit -> data);
visit = visit -> link;
}
}
/////////////////////////////////////////////////////////////////////////////////
/*
void bubble_sort(node **List,int size)
{
int i,j,temp;
node*first;
node*second;
node*final;
final=*List;
for(i=0;i<size-1;i++)
{
first=final;
second=first->link;
for(j=1;j<size;j++)
{
if( first->data<second->data)
{
temp=first->data;
first->data=second->data;
second->data=temp;
}
first=first->link;
}
}
*List=first;
} */
//////////////////////////////////////////////////////////////////////////////////////
void bubble_sort(node * * List, int size)
{
int i, j, temp;
node * first;
node * second;
node * final;
for (i = 0; i < size; i++)
{
first = * List;
for (j = 0; j < size - 1; j++)
{
if (first -> data < first -> link -> data)
{
temp = first -> data;
first -> data = first -> link -> data;
first -> link -> data = temp;
}
first = first -> link;
}
}
}
////////////////////////////////////////////////////////////////////////////////////////////
main()
{
start = NULL;
int val, n, size;
char ch;
struct node * new;
new = NULL;
printf("\nEnter the size desired size of Linked list: \n");
scanf("%d", & size);
for (ch = 0; ch < size; ch++)
{
printf("\nEnter a value: ");
scanf("%d", & val);
append( & new, val);
}
start = new;
displaylist(start);
printf("\nApplying Bubble sort on Linked list: \n");
bubble_sort( & start, val);
displaylist(start);
printf("\n");
}
Assumed Val is number of nodes in list, you are actually not sorting a linked list but instead swapping the values from one node to another in order to sort it.
bubble_sort( &start, size); change this as well should fix it(pass size not val)
try this.
void bubble_sort(node **List, int val)
{
int i,j,temp;
node *first;
node *second;
node *final;
for(i = 0; i < val; i++)
{
first = *list
for(j = 0; j < val-1; j++)
{
if(first->data < first->link->data)
{
temp = first->data;
first->data = first->link->data;
first->link->data = temp;
}
first = first->link;
}
}
}
I believe you are getting a segmentation fault because you're trying to access a Null pointer as a node, in the inner for-loop.
for (j = 0; j < val; j++)
this should be:
for (j = 0; j < val - 1; j++)
Because in your solution, when j = val-1, it will still try and access first->link->data, however, first->link is Null.
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.
I am trying to do an efficient sparse matrix multiplication. Right now I am reading the data into memory and this is how my data structure looks like:
typedef struct node{
int x;
int y;
int value;
struct node* row;
struct node* col;
}node;
typedef struct matrix{
int height;
int width;
node** rowList;
node** colList;
}matrix;
My current code for the insertion is:
void insert(matrix** M, int row_index, int col_index, int value)
{
node* currNode=(node*)malloc(sizeof(node));
currNode->x=row_index;
currNode->y=col_index;
currNode->value=value;
if ((*M)->rowList[row_index] == NULL) { /* index is empty */
currNode->row = NULL;
(*M)->rowList[row_index] = currNode;
}
else if ((*M)->rowList[row_index]->y > col_index) { /* insert node to front */
//printf("%d, %d\n", (*M)->rowList[row_index]->y, col_index);
currNode->col = (*M)->rowList[row_index];
(*M)->rowList[row_index] = currNode;
}
else if ((*M)->rowList[row_index]->y < col_index) { /* insert node to front */
node* rowptr = (node*)malloc(sizeof(node));
rowptr = (*M)->rowList[row_index];
while(rowptr->col!=NULL&&rowptr->col->y < col_index)
rowptr=rowptr->col;
currNode->col=rowptr->col;
rowptr->col=currNode;
//printf("-----------------%d\n", rowptr->y);
}
if ((*M)->colList[col_index] == NULL) {
currNode->col = NULL;
(*M)->colList[col_index] = currNode;
}
else
if ((*M)->colList[col_index]->x > row_index) {
//printf("%d, %d\n", (*M)->colList[col_index]->x, row_index);
currNode->row = (*M)->colList[col_index];
(*M)->colList[col_index] = currNode;
}
}
In case of you ask, this is my print function:
void print_matrix(matrix *M){
for(int i=0;i<M->height;i++){
while(M->rowList[i]!=NULL){
printf("i=%d, j=%d, v=%d\n",M->rowList[i]->x, M->rowList[i]->y,
M->rowList[i]->value);
M->rowList[i]=M->rowList[i]->col;
}
}
}
For this input:
5,5
0,0,1
0,1,2
0,3,3
0,4,4
where (5,5) matrix dimensions and (0,0,1) = i,j,value, I get this:
i=0, j=0, v=1
i=0, j=1, v=2
i=0, j=3, v=3
i=0, j=4, v=4
i=0, j=4, v=4
For this input:
5,5
0,0,1
0,1,2
0,3,3
0,4,4
0,2,5
I get this:
i=0, j=0, v=1
i=0, j=1, v=2
i=0, j=2, v=5
i=0, j=2, v=5
I think the problem is here:
else if ((*M)->rowList[row_index]->y < col_index) {
node* rowptr = (node*)malloc(sizeof(node));
rowptr = (*M)->rowList[row_index];
while(rowptr->col!=NULL&&rowptr->col->y < col_index)
rowptr=rowptr->col;
currNode->col=rowptr->col;
rowptr->col=currNode;
}
[ ... ]
Somehow I remove one of the values when I add a new element that is smaller.
The question is : how can I get this code to load my sparse matrix values into memory using the data structure provided correctly?
Thank you ^^
Here:
if ((*M)->colList[col_index] == NULL) {
currNode->col = NULL;
(*M)->colList[col_index] = currNode;
}
where you write currNode->col, you should have written currNode->row. After making this change the output is correct for the second input file.
While looking at the code I noticed other odd things; for example, the print_matrix function also destroys the matrix ->col pointer chains. Also, in these two lines
node* rowptr = (node*)malloc(sizeof(node));
rowptr = (*M)->rowList[row_index];
you're allocating memory and then immediately overwriting the pointer to it.