Sparse matrix insert in c - c

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.

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])

C How to find and group coordinates located in a grid

I have a C program where a CSV file containing 8 x,y coordinates are inserted into a linked list.
Each of the 8 coordinates belongs in a 2x2 grid. There are 4 grids as seen in the picture below:
First I want my program to determine which coordinate belongs in which grid. Once I've determined that, for each grid, I want to sum all of the x-coordinates and y-coordinates. Then for each grid 1-4, I want to then print the total sum of the x coord and y coord.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <sys/time.h>
#include <string.h>
#define MAX 200
struct wake {
double x, y;
struct wake *next;
}*head;
typedef struct {
double x, y;
} grid_t;
typedef struct wake data;
void read_csv();
void gridSearch();
void maxNode();
int main(int argc, char *argv[]) {
read_csv();
}
void read_csv() {
// Opens the CSV datafile
FILE *fp = fopen("data4.csv", "r");
char buffer[MAX];
struct wake** tail = &head;
while (fgets(buffer, MAX, fp)) {
data *node = malloc(sizeof(data));
node->x = atof(strtok(buffer, ","));
node->y = atof(strtok(NULL, ","));
node->next = NULL;
*tail = node;
tail = &node->next;
}
gridSearch();
//maxNode();
}
void gridSearch() {
struct wake *current = head;
int i, j, gridnum = 0;
grid_t (*grid)[2] = calloc(4, sizeof(grid_t[2][2]));
//double min;
if(head == NULL) {
printf("List is empty \n");
}
else {
//Initializing min with head node data
while(current != NULL){
for (j = 0; j < 2; j++) {
for (i = 0; i < 2; i++) {
if ((current->x >= -2+i*2) && (current->x <= -2+(i+1)*2)) {
if ((current->y >= -2+j*2) && (current->x <= -2+(j+1)*2)) {
printf("%lf\n", current->x);
grid[i][j].x += current->x;
grid[i][j].y += current->y;
}
}
}
}
current= current->next;
}
}
for (i = 0; j < 2; j++) {
for (j = 0; i < 2; i++) {
gridnum++;
printf("Sum of x coord in grid %d: %lf\n", gridnum, grid[i][j].x);
printf("Sum of y coord in grid %d: %lf\n\n", gridnum, grid[i][j].y);
}
}
}
When I run my program, nothing seems to happen. I'm not sure why it's not working.
Here is the input CSV file:
-1,-1
-1,1.5
1,-1
1,1
-1.5,-1.5
-1,0.5
1.5,-1.5
0.5,0.5

How do implement Count sort using linked list?

What I am trying to do is to create a counting sort using a linked list so I can link two similar elements in the same index and then copy from left to right to the original array. But my Buckets[i] are always NULL even after insertion. So my resulting array does not change. I don't know what I am doing wrong.
#include <stdio.h>
#include <stdlib.h>
struct Node {
int data;
struct Node *next;
} **Buckets;
void printArray(int arr[], int size) {
for (int i = 0; i < size; i++)
printf("%d ", arr[i]);
printf("\n");
}
int findMax(int A[], int n) {
int i, max = A[0];
for (i = 0; i < n; i++) {
if (A[i] > max)
max = A[i];
}
return max;
}
void Insert(struct Node *p, int x) {
while (p != NULL) {
p = p->next;
}
Node *t = t = (struct Node *)malloc(sizeof(struct Node));
t->data = x;
t->next = NULL;
p = t;
}
int Delete(struct Node *Buckets) {
while (Buckets->next != NULL) {
Buckets = Buckets->next;
}
int temp = Buckets->data;
free(Buckets);
return temp;
}
void BucketSort(int A[], int size) {
int max, i, j;
max = findMax(A, size);
Buckets = new Node * [max + 1];
for (i = 0; i < max + 1; i++) {
Buckets[i] = NULL;
}
for (i = 0; i < size; i++) {
Insert(Buckets[A[i]], A[i]); //insertion
}
i = j = 0;
while (i < max + 1) {
while (Buckets[i] != NULL) {
A[j++] = Delete(Buckets[i]); // copy back in array
}
i++;
}
}
int main() {
int arr[] = { 3, 8, 5, 1, 10 };
int size = sizeof(arr) / sizeof(arr[0]); //5
printf("\nBefore : ");
printArray(arr, size);
BucketSort(arr, size);
printf("\nAfter : ");
printArray(arr, size);
return 0;
}
Your Insert function doesn't really modify the list – you just assign the new node to a local variable, which goes out of scope immediately.
You can solve this by passing a pointer to a node pointer to the function. That pointer points at the head pointer at first and at the next member of the preceding node when you advance:
void Insert(struct Node **p, int x)
{
while (*p) p = &(*p)->next;
*p = new Node(x); // assume a c'tor here
}
Call the function like so:
for (i = 0; i < size; i++) {
Insert(&Buckets[A[i]] ,A[i]);
}
The same goes for deletion: You must modify the links or the list head when you delete:
int Delete(struct Node **p)
{
int temp = (*p)->data;
struct Node *del = *p;
*p = (*p)->next;
delete del;
return temp;
}
(This code extracts the head node, which is probably what you want: You insert at the end, then retrieve from the beginning. That should preserve the original order. Not that it matters miuch in your case, where you have no data beside the int.)
Call Delete like so:
i = j = 0;
while (i < max + 1) {
while (Buckets[i]) {
A[j++] = Delete(&Buckets[i]);
}
i++;
}

Why is my code giving me garbage values and sometimes segmentation fault?

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++];

trying to print a array of structs in C

I was asked to build a function that's receive a static two dimensional array with a lot of zeroes and turn it to an array of structs. each struct contains the value which is not zero and the index of the column.
Now I have built it but the problem is with the print function.
1) When I try to print twice it only prints one time and the second time list becomes NULL. Why does this occur?
print(list);
print(list);
2) Why can't I print like I did in the main function?
printf("this is just a print |%d||%d| ", list[0]->next->next->next->data, list[0]->col);
Why I don't have access to it, the program crashes...
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
//#include <vld.h>
#include <string.h>
#include <ctype.h>
#define C 5
#define N 4
typedef struct Node {
int data;
int col;
struct Node *next;
} node;
node **fun(int arr[N][C]) {
int i, j, k;
node **list;
node *temp;
list = (node**)calloc(N, sizeof(node *));
for (i = 0; i < N; i++) {
list[i] = NULL;
for (j = C - 1; j >= 0; j--)
if (arr[i][j] != 0) {
temp = (node*)malloc(sizeof(node));
temp->data = arr[i][j];
temp->col = j;
temp->next = list[i];
list[i] = temp;
}
}
return list;
}
void print(node **head) {
int i;
node **temp = head;
for (i = 0; i < N; i++) {
while (temp[i]) {
printf("|%d||%d| ", temp[i]->data, temp[i]->col);
temp[i] = temp[i]->next;
}
printf("\n\n");
}
}
void main() {
int arr[N][C] = { {0,0,4,0,7}, {3,0,0,0,0}, {9,1,0,6,0} , {0,0,0,0,0} };
node **list;
list = fun(arr);
print(list); ///////////
print(list); ///////////////
printf("this is just a print |%d||%d| ", list[0]->next->next->next->data, list[0]->col);
}
As was mentioned in the comments, you are destroying your list of pointer in the process of printing them:
while(temp[i])
{ printf("|%d||%d| ",temp[i]->data,temp[i]->col);
temp[i]=temp[i]->next; // <---- here
}
Each temp[i] is the same as head[i], so you modify the original list as you do this. The while loop exits when this value is NULL, so the end result is that all array elements are NULL.
You need to assign this value to a temporary so you can walk the list without changing it:
node *temp2 = temp[i];
while(temp2)
{ printf("|%d||%d| ",temp2->data,temp2->col);
temp2=temp2->next;
}
Your print function modifies the array: it uses the array elements to iterate through the lists, and leaves them with a NULL value.
Here is a corrected version:
void print(node **head) {
int i;
for (i = 0; i < N; i++) {
node *temp;
for (temp = head[i]; temp; temp = temp->next) {
printf("|%d||%d| ", temp->data, temp->col);
}
printf("\n\n");
}
}

Resources