matrix product between linked list sparse matrix - c

i've rappresented my sparse matrix in that form, using C language:
typedef struct node
{
int column;
int value;
int row;
struct node *next;
} element;
i've got an Insert function that add an element in the matrix, here's the declaration:
void Insert(element *x[], int row, int column, int value)
my question is: how i can implement a function that compute the product between two sparse matrix in that form?
here's is my tentative:
void dotProduct( element * ptrA , element * ptrB ) {
element* initB = ptrB;
int sum = 0;
while( ptrA!=NULL ) {
ptrB = initB;
int column, int row;
while( ptrB!=NULL ) {
if( ptrA->row == ptrB->column ) {
column = ptrb->column;
sum = sum + ptra->value*ptrB->value;
row = ptrA->row;
}
ptrB = ptr->next;
}
ptrA = ptrA->next;
}
insert( row, column, sum )
}

You have a good start. But your sum variable is computing the sum of all elements of the result matrix. That's not what you want.
Here is what I would change.
1) Instead of a scalar integer int sum = 0 use a sparse matrix elment *result = NULL. You want to add the value to a specific element of the matrix, not to a scalar sum.
2) Add a function to add increase the value of a matrix element (row, column) by an int value
void Add(element *x[], int row, int column, int value){
element *ptr = x;
while (ptr != NULL) {
if (ptr->row == row && ptr->column == column) {
ptr->value += value;
return;
}
}
/* We could not find an existing element with given row and column
Create a new one */
Insert(x, row, column, value)
}
3) Replace sum = sum + ptra->value*ptrB->value; with Add(result, row, column, ptra->value*ptrB->value);
4) You can get rid of your final insert( row, column, sum ). It won't compile as it has only 3 parameters. By the time your outer while loop completes, you'll have a computed product in the sparse matrix result anyway.

Related

Recovering elements of large array with multiple index ranges

This is a tricky problem that I have been thinking about for a long time and have yet to see a satisfactory answer anywhere. Lets say I have a large int array of size 10000. I can simply declare it in the following manner:
int main()
{
int foo[10000];
int i;
int n;
n = sizeof(foo) / sizeof(int);
for (i = 0; i < n; i++)
{
printf("Index %d is %d\n",i,foo[i] );
}
return 0;
}
It is pretty clear that each index in the array will hold a random assortment of numbers before I formally initialize them:
Index 0 is 0
Index 1 is 0
Index 2 is 0
Index 3 is 0
.
.
.
Index 6087 is 0
Index 6088 is 1377050464
Index 6089 is 32767
Index 6090 is 1680893034
.
.
.
Index 9996 is 0
Index 9997 is 0
Index 9998 is 0
Index 9999 is 0
Then lets say that I initialize select index ranges of my array with values that hold a specific value for the program as a whole and must be preserved, with the goal of passing in those values for subsequent operation to some function:
//Call this block 1
foo[0] = 0;
foo[1] = 7;
foo[2] = 99;
foo[3] = 0;
//Call this block 2
foo[9996] = 0;
foo[9997] = 444;
foo[9998] = 2;
foo[9999] = 0;
for (i = 0; i < (What goes here?); i++)
{
//I must pass in only those values initialized to select indices of foo[] (Blocks 1 and 2 uncorrupted)
//How to recover those values to pass into foo_func()?
foo_func(foo[]);
}
Some of those values that I initialized foo[] with overlap with pre-existing values in the array before formally initializing the array myself. How can I pass in just the indices of the array elements that I initialized, given that there are multiple index ranges? I just can't figure this out. Thanks for any and all help!
EDIT:
I should also mention that the array itself will be read from a .txt file. I just showed the initialization in the code for illustrative purposes.
There's a number of ways you can quickly zero out the memory in the array, either while initializing or after.
For an array on the stack, initialize it with zeros. {0} is shorthand for that.
int foo[10000] = {0};
For an array on the heap, use calloc to allocate memory and initialize it with 0's.
int *foo = calloc(10000, sizeof(int));
If the array already exists, use memset to quickly overwrite all the array's memory with zeros.
memset(foo, 0, sizeof(int) * 10000);
Now all elements are zero. You can set individual elements to whatever you like one by one. For example...
int main() {
int foo[10] = {0};
foo[1] = 7;
foo[2] = 99;
foo[7] = 444;
foo[8] = 2;
for( int i = 0; i < 10; i++ ) {
printf("%d - %d\n", i, foo[i]);
}
}
That will print...
0 - 0
1 - 7
2 - 99
3 - 0
4 - 0
5 - 0
6 - 0
7 - 444
8 - 2
9 - 0
As a side note, using only a few elements of a large array is a waste of memory. Instead, use a hash table, or if you need ordering, some type of tree. These can be difficult to implement correctly, but a library such as GLib can provide you with good implementations.
Introduction
I'm making a strong assumption on your problem, and it is sparsness (a majority of the elements in your array will remain zero).
Under this assumption I would build the array as a list. I'm including a sample code, that it is not complete and it is not intended to
be---you should do your own homework :)
The core object is a struct with a pointer to a begin element and the size:
typedef struct vector {
size_t size;
vector_element_t * begin;
} vector_t;
each element of the vector has its own index and value and a pointer to the next element in a list:
typedef struct vector_element vector_element_t;
struct vector_element {
int value;
size_t index;
vector_element_t *next;
};
on this basis we can build a dynamical vector as a list, by dropping a constraint on the ordering (it is not needed, you can modify this code
to maintain the ordering), using some simple custom methods:
vector_t * vector_init(); // Initialize an empty array
void vector_destroy(vector_t* v); // Destroy the content and the array itself
int vector_get(vector_t *v, size_t index); // Get an element from the array, by searching the index
size_t vector_set(vector_t *v, size_t index, int value); // Set an element at the index
void vector_delete(vector_t *v, size_t index); // Delete an element from the vector
void vector_each(vector_t *v, int(*f)(size_t index, int value)); // Executes a callback for each element of the list
// This last function may be the response to your question
Test it online
The main example
This is a main that uses all this methods and prints in console:
int callback(size_t index, int value) {
printf("Vector[%lu] = %d\n", index, value);
return value;
}
int main() {
vector_t * vec = vector_init();
vector_set(vec, 10, 5);
vector_set(vec, 23, 9);
vector_set(vec, 1000, 3);
printf("vector_get(vec, %d) = %d\n", 1000, vector_get(vec, 1000)); // This should print 3
printf("vector_get(vec, %d) = %d\n", 1, vector_get(vec, 1)); // this should print 0
printf("size(vec) = %lu\n", vec->size); // this should print 3 (the size of initialized elements)
vector_each(vec, callback); // Calling the callback on each element of the
// array that is initialized, as you asked.
vector_delete(vec, 23);
printf("size(vec) = %lu\n", vec->size);
vector_each(vec, callback); // Calling the callback on each element of the array
vector_destroy(vec);
return 0;
}
And the output:
vector_get(vec, 1000) = 3
vector_get(vec, 1) = 0
size(vec) = 3
Vector[10] = 5
Vector[23] = 9
Vector[1000] = 3
size(vec) = 3
Vector[10] = 5
Vector[1000] = 3
The callback with the function vector_each is something you really should look at.
Implementations
I'm giving you some trivial implementations for the functions in the introdution. They are not complete,
and some checks on pointers should be introduced. I'm leaving that to you. As it is, this code is not for production and under some circumstances can also overflow.
The particular part is the search of a specific element in the vector. Every time you tranverse the list,
and this is convenient only and only if you have sparsity (the majority of your index will always return zero).
In this implementation, if you access an index that is not enlisted, you get as a result 0. If you don't want this
you should define an error callback.
Initialization and destruction
When we initialize, we allocate the memory for our vector, but with no elements inside, thus begin points to NULL. When we destroy the vector we have not only to free the vector, but also each element contained.
vector_t * vector_init() {
vector_t * v = (vector_t*)malloc(sizeof(vector_t));
if (v) {
v->begin = NULL;
v->size = 0;
return v;
}
return NULL;
}
void vector_destroy(vector_t *v) {
if (v) {
vector_element_t * curr = v->begin;
if (curr) {
vector_element_t * next = curr->next;
while (next) {
curr = curr->next;
next = next->next;
if (curr)
free(curr);
}
if (next)
free(next);
}
free(v);
}
}
The get and set methods
In get you can see how the list works (and the same concept
is used also in set and delete): we start from the begin, and
we cross the list until we reach an element with an index equal
to the one requested. If we cannot find it we simply return 0.
If we need to "raise some sort of signal" when the value is
not found, it is easy to implement an "error callback".
As long as sparsness holds, searching in the whole array for an index is a good compromise in terms of memory requirements, and efficiency may be not an issue.
int vector_get(vector_t *v, size_t index) {
vector_element_t * el = v->begin;
while (el != NULL) {
if (el->index == index)
return el->value;
el = el->next;
}
return 0;
}
// Gosh, this set function is really a mess... I hope you can understand it...
// -.-'
size_t vector_set(vector_t *v, size_t index, int value) {
vector_element_t * el = v->begin;
// Case 1: Initialize the first element of the array
if (el == NULL) {
el = (vector_element_t *)malloc(sizeof(vector_element_t));
if (el != NULL) {
v->begin = el;
v->size += 1;
el->index = index;
el->value = value;
el->next = NULL;
return v->size;
} else {
return 0;
}
}
// Case 2: Search for the element in the array
while (el != NULL) {
if (el->index == index) {
el->value = value;
return v->size;
}
// Case 3: if there is no element with that index creates a new element
if (el->next == NULL) {
el->next = (vector_element_t *)malloc(sizeof(vector_element_t));
if (el->next != NULL) {
v->size += 1;
el->next->index = index;
el->next->value = value;
el->next->next = NULL;
return v->size;
}
return 0;
}
el = el->next;
}
}
Deleting an element
With this approach it is possible to delete an element quite easily, connecting
curr->next to curr->next->next. We must though free the previous curr->next...
void vector_delete(vector_t * v, size_t index) {
vector_element_t *curr = v->begin;
vector_element_t *next = curr->next;
while (next != NULL) {
if (next->index == index) {
curr->next = next->next;
free(next);
return;
} else {
curr = next;
next = next->next;
}
}
}
An iteration function
I think this is the answer to the last part of your question,
instead passing a sequence of indexes, you pass a callback to the vector.
The callback gets and sets value in a specific index. If you want to
operate only on some specific indexes, you may include a check in the
callback itself. If you need to pass more data to the callback, check
the very last section.
void vector_each(vector_t * v, int (*f)(size_t index, int value)) {
vector_element_t *el = v->begin;
while (el) {
el->value = f(el->index, el->value);
el = el->next;
}
}
Error callback
You may want to raise some out of bounds error or something else. One solution is to enrich your list with function pointer that represent a callback that should be called when your user sk for an undefined element:
typedef struct vector {
size_t size;
vector_element_t *begin;
void (*error_undefined)(vector *v, size_t index);
} vector_t
and maybe at the end of your vector_get function you may want to do something like:
int vector_get(vector_t *v, size_t index) {
// [ . . .]
// you know at index the element is undefined:
if (v->error_undefined)
v->error_undefined(v, index);
else {
// Do something to clean up the user mess... or simply
return 0;
}
}
usually it is nice to add also an helper function to set the callback...
Passing user data to "each" callback
If you want to pass more data to the user callback, you may add a void* as last argument:
void vector_each(vector_t * v, void * user_data, int (*f)(size_t index, int value, void * user_data));
void vector_each(vector_t * v, void * user_data, int (*f)(size_t index, int value, void * user_data)) {
[...]
el->value = f(el->index, el->value, user_data);
[...]
}
if the user do not need it, he can pass a wonderful NULL.

Quick sort and bubble sort give different results

I'm facing with a singular issue:
I have a big table which content is a lot of pair of numbers. I have to sort them in descending order. I wrote a BubbleSort procedure and works fine, but is very slow to do its job. So I used a QuickSort procedure and... Data inside of the array changes after the sort!
So I tried with a sample table, with similar dimensions and "easy-to-write" content, basically a cicle which assign to
table[i][0]=i*3
and
table[i][1]=i*5
and... Works fine.
The code used is the following:
typedef struct MATCHES {
short size;
unsigned short values[10000][2];
} MATCHES;
int partition(MATCHES **data, int left, int right, int pivot, int col){
int temp;
int i;
int storeIndex = left;
int pivotVal = (**data).values[pivot][col];
(**data).values[pivot][col] = (**data).values[right][col];
(**data).values[right][col] = pivotVal;
for(i = left; i < right; i++){
if ((**data).values[i][col] >= pivotVal){ //Change this to greater then and BOOM we're done
temp = (**data).values[i][col];
(**data).values[i][col] = (**data).values[storeIndex][col];
(**data).values[storeIndex][col] = temp;
storeIndex++;
}
}
temp = (**data).values[storeIndex][col];
(**data).values[storeIndex][col] = (**data).values[right][col];
(**data).values[right][col] = temp;
return storeIndex;
}
void quickSort(MATCHES **vec, int left, int right, int col) {
int r;
if (right > left) {
r = partition(vec, left, right, right+1/2, col);
quickSort(vec, left, r - 1, col);
quickSort(vec, r + 1, right, col);
}
}
void sorter(MATCHES *table) {
quickSort(&table, 0, (*table).size-1, 0);
quickSort(&table, 0, (*table).size-1, 1);
}
int main () {
MATCHES table;
table.size=10000;
int i;
for (i=0; i<table.size; i++) {
table.values[i][0]=i*3;
table.values[i][1]=i*5;
}
printf("Unsorted\n");
for (i=0; i<table.size; i++)
printf("%d %d\n",table.values[i][0],table.values[i][1]);
sorter(&table);
printf("Sorted\n");
for (i=0; i<table.size; i++)
printf("%d %d\n",table.values[i][0],table.values[i][1]);
return 0;
}
For doing another try, I took the data I need to sort into this program and result is again wrong.
I'll link the code, since is very long due the initialization vector.
http://pastebin.com/Ztwu6iUP
Thanks in advance for any help!
EDIT:
I found a partial solution. Instead of using quickSort, that is unstable, I used mergeSort. Now, when I sort the second time the table, for every duplicate (or three times the same value) on the second column, in the first I have data sorted in ascending order.
The code is the following:
void merge(MATCHES *v, int i1, int i2, int fine, int col, MATCHES *vout) {
int i=i1, j=i2, k=i1;
while (i<=i2-1 && j<=fine) {
if ((*v).values[i][col]>(*v).values[j][col]) {
(*vout).values[k][0]=(*v).values[i][0];
(*vout).values[k][1]=(*v).values[i][1];
i++;
}
else {
(*vout).values[k][0]=(*v).values[j][0];
(*vout).values[k][1]=(*v).values[j][1];
j++;
}
k++;
}
while (i<=i2-1){
(*vout).values[k][0]=(*v).values[i][0];
(*vout).values[k][1]=(*v).values[i][1];
i++;
k++;
}
while (j<=fine){
(*vout).values[k][0]=(*v).values[j][0];
(*vout).values[k][1]=(*v).values[j][1];
j++;
k++;
}
for (i=i1; i<=fine; i++) {
(*v).values[i][0]=(*vout).values[i][0];
(*v).values[i][1]=(*vout).values[i][1];
}
}
void mergeSort(MATCHES *v, int iniz, int fine, int col, MATCHES *vout) {
int mid;
if(iniz<fine){
mid=(fine+iniz)/2;
mergeSort(v, iniz, mid, col, vout);
mergeSort(v, mid+1, fine, col, vout);
merge(v, iniz, mid+1, fine, col, vout);
}
}
Any hint for this?
In order to use quicksort to get stability, you need to answer the following question.
Can I tell the difference between a1 and a2?
If a1 and a2 differ because they have a secondary field, then there is a 'stable' solution with quick sort.
If a1 and a2 differ because they were added at different times (a field which doesn't matter), then the sort is unstable and will sometimes have a1 before a2 and sometimes after.
In your question, it is not clear if these numbers are linked
1,9
5,8
3,7
4,6
Should that go to :-
1,6
3,7
4,8
5,9
or
4,6
3,7
5,8
1,9
Are there 2 independent sorts? or is it a secondary field sort.
The merge code looks like a secondary field sort.
Sort on a secondary field
To sort on a secondary field, the comparison needs to be like :-
int compare( Atype* lhs, Atype * rhs )
{
if( lhs->field1 < rhs->field1 ) return -1;
if( lhs->field1 > rhs->field1 ) return 1;
if( lhs->field2 < rhs->field2 ) return -1;
if( lhs->field2 > rhs->field2 ) return 1;
/* more fields can be added here */
return 0;
}
Instead of sorting columns independently
quickSort(&table, 0, (*table).size-1, 0);
quickSort(&table, 0, (*table).size-1, 1);
Try the following.
Combining the sort into one go :-
quickSort(&table, 0, (*table).size-1 );
Change the comparison to take base array
int compare( short * lhs, short * rhs ) /* sort by 1 then 0 */
{
if( lhs[1] < rhs[1] ) return -1;
if( lhs[1] > rhs[1] ) return 1;
if( lhs[0] < rhs[0] ) return -1;
if( lhs[0] > rhs[0] ) return 1;
return 0;
}
Partition becomes
int partition(MATCHES **data, int left, int right, int pivot, int col){
int temp;
int i;
int storeIndex = left;
short pivotVal[2];
pivotVal[0] = (**data).values[pivot][0];
pivotVal[1] = (**data).values[pivot][1];
/* here you were jumbling pivot value - not keeping [0,1] together */
(**data).values[pivot][0] = (**data).values[right][0];
(**data).values[pivot][1] = (**data).values[right][1];
(**data).values[right][0] = pivotVal[0];
(**data).values[right][1] = pivotVal[1];
for(i = left; i < right; i++){
if ( compare( (**data).values[i] , pivotVal ) >= 0){ //Change this to greater then and BOOM we're done
temp = (**data).values[i][0];
(**data).values[i][0] = (**data).values[storeIndex][0];
(**data).values[storeIndex][0] = temp;
temp = (**data).values[i][1];
(**data).values[i][1] = (**data).values[storeIndex][1];
(**data).values[storeIndex][1] = temp;
storeIndex++;
}
}
temp = (**data).values[storeIndex][0];
(**data).values[storeIndex][0] = (**data).values[right][0];
(**data).values[right][0] = temp;
temp = (**data).values[storeIndex][1];
(**data).values[storeIndex][1] = (**data).values[right][1];
(**data).values[right][1] = temp;
return storeIndex;
}

Getting the values of linked list with loops

I have to create a function who can get the value of a matrix wich take the form of a double linked list. Here is the structures of the matrix
typedef struct row {
unsigned int indiceRow;
struct row * next;
struct col * data;
} row;
typedef struct col{
double value;
unsigned int indiceColumn;
struct col * next;
} col;
typedef struct matrix{
int nRows;
int nCols;
struct row * rowFirst;
}matrix;
the structure matrix represent the top of the linked list and contain the total number of rows and columns and a variable row wich point to the first node of the list of row nodes. the row nodes contain the number of the row of the matrice, a variable row called next wich represent the next line of the matrix and a variable data point to another list of col nodes. Those col nodes contains the number of the column, the value at those coordonates(row,column) and the a col next. only the values different of zero have to be in the col linked list.
To get the value of a precise point of the matrix I created the function sp_get. It take a structure matrix, the line and column I'm looking for and a double variable as argument. It returns 0 when it works and update the variable double *val with the value I'm looking for.
int sp_get( struct matrix *mat, unsigned int rows, unsigned int col, double *val){
row * temps = (row*)malloc(sizeof(row));
temps = mat->rowFirst;
while(temps->indiceRow!= rows){
temps = temps->next;
}
while(temps->data!= NULL && temps->data->indiceColumn!= col && temps->data->next!=NULL){
temps->data = temps->data->next;
}
if(temps->data->indiceColumn == col){
*(val) = temps->data->value;
}
else{
*(val) = 0.0;
}
return 0;
First I create a row variable to run through the matrix, then I look for the good row and then for the good column. If I can't find the good column it means that the value is 0.
When I use the function to look for one value, it works well, and always return the good value.(tempMatrix is a matrix variable and contain the linked list)
double * vall =(double*)malloc(sizeof(double));
sp_get(tempMatrix, 2, 3, vall);
but when I'm using the function with a double loop for I don't have the same results and I can't not explain why...
double * vall =(double*)malloc(sizeof(double));
int i;
int j;
for(i=1;i<=tempMatrix->nRows;i++){
for(j=1; j<=tempMatrix->nCols;j++){
sp_get(tempMatrix,i,j,vall);
printf(" %f ", *(vall));
}
printf("\n");
}
Here are the result I get with the loops
and here are the results I should get
It might be a proble of memory leak, I don't know where it comes from.
Thanks in advance for your help!
Just in sp_get alone the following problems abound:
Memory the first two lines.
Anytime you see something like this in successive lines in C:
ptr = malloc(...)
ptr = <something else>
it is always a memory leak.
Updating the column header rather than simply enumerating it
Once you find the row you seek, you then do this:
while(temps->data!= NULL &&
temps->data->indiceColumn!= col &&
temps->data->next!=NULL)
{
temps->data = temps->data->next;
}
Ask yourself, what is temps->data = ... actually updating? It is changing the temps->data pointer to point to its own next, which means what temps->data pointed to prior is gone. That's fine if temps->data is a temporary pointer, but it isn't. It is the data member in the row struct you worked so hard to find in the prior loop.
Potential NULL pointer dereference
You may think having this:
while(temps->data!= NULL &&
temps->data->indiceColumn!= col &&
temps->data->next!=NULL)
for the while-condition in your loop will harbor safety from temp-data being NULL for the code that follows:
if(temps->data->indiceColumn == col)
{
*(val) = temps->data->value;
}
but if it did, then why bother with the first clause (which is correct, btw). It appears the addition of the last clause (temps->data->next!=NULL) was an effort to stave off crashes. That isn't the way to do it.
Minor: Hiding type col with parameter col
Needs little explanation. See your var names.
Minor: There is no need to dynamically allocate the out-parameter as you're using it.
Your code do to this:
double * vall =(double*)malloc(sizeof(double));
int i, j;
for(i=1;i<=tempMatrix->nRows;i++)
{
for(j=1; j<=tempMatrix->nCols;j++)
{
sp_get(tempMatrix,i,j,vall);
printf(" %f ", *(vall));
}
printf("\n");
}
Can just as easily do this:
double val = 0.0;
int i, j;
for(i=1;i<=tempMatrix->nRows;i++)
{
for(j=1; j<=tempMatrix->nCols;j++)
{
sp_get(tempMatrix,i,j,&val); // note address-of operator
printf(" %f ", val);
}
printf("\n");
}
Updated sp_get
I'm pretty sure this is what you're trying to do. The following will return 0 if the indexed values found and retrieved, otherwise it returns -1 and the out-parameter is set to 0.0.
int sp_get( struct matrix const *mat, unsigned int rows, unsigned int cols, double *val)
{
// prime to 0.0
*val = 0.0;
if (!mats)
return -1;
// walk the row table
struct row const *row_ptr = mat->rowFirst;
while (row_ptr && row_ptr->indiceRow != rows)
row_ptr = row_ptr->next;
// leave now if we didn't find the row.
if (!row_ptr)
return -1;
struct col const *col_ptr = row_ptr->data;
while (col_ptr && col_ptr->indiceColumn != cols)
col_ptr = col_ptr->next;
if (!col_ptr)
return -1;
*val = col_ptr->value;
return 0;
}
Note we modify nothing in the actual matrix, so the entire thing, including all pointers we use to index within it, can be const (and should be).
Best of luck.

Sorting an array of coordinates by their distance from origin

The code should take an array of coordinates from the user, then sort that array, putting the coordinates in order of their distance from the origin. I believe my problem lies in the sorting function (I have used a quicksort).
I am trying to write the function myself to get a better understanding of it, which is why I'm not using qsort().
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define MAX_SIZE 64
typedef struct
{
double x, y;
}POINT;
double distance(POINT p1, POINT p2);
void sortpoints(double distances[MAX_SIZE], int firstindex, int lastindex, POINT data[MAX_SIZE]);
void printpoints(POINT data[], int n_points);
int main()
{
int n_points, i;
POINT data[MAX_SIZE], origin = { 0, 0 };
double distances[MAX_SIZE];
printf("How many values would you like to enter?\n");
scanf("%d", &n_points);
printf("enter your coordinates\n");
for (i = 0; i < n_points; i++)
{
scanf("%lf %lf", &data[i].x, &data[i].y);
distances[i] = distance(data[i], origin); //data and distances is linked by their index number in both arrays
}
sortpoints(distances, 0, i, data);
return 0;
}
double distance(POINT p1, POINT p2)
{
return sqrt(pow((p1.x - p2.x), 2) + pow((p1.y - p2.y), 2));
}
void printpoints(POINT *data, int n_points)
{
int i;
printf("Sorted points (according to distance from the origin):\n");
for (i = 0; i < n_points; i++)
{
printf("%.2lf %.2lf\n", data[i].x, data[i].y);
}
}
//quicksort
void sortpoints(double distances[MAX_SIZE], int firstindex, int lastindex, POINT data[MAX_SIZE])
{
int indexleft = firstindex;
int indexright = lastindex;
int indexpivot = (int)((lastindex + 1) / 2);
int n_points = lastindex + 1;
double left = distances[indexleft];
double right = distances[indexright];
double pivot = distances[indexpivot];
POINT temp;
if (firstindex < lastindex) //this will halt the recursion of the sorting function once all the arrays are 1-size
{
while (indexleft < indexpivot || indexright > indexpivot) //this will stop the sorting once both selectors reach the pivot position
{
//reset the values of left and right for the iterations of this loop
left = distances[indexleft];
right = distances[indexright];
while (left < pivot)
{
indexleft++;
left = distances[indexleft];
}
while (right > pivot)
{
indexright--;
right = distances[indexright];
}
distances[indexright] = left;
distances[indexleft] = right;
temp = data[indexleft];
data[indexleft] = data[indexright];
data[indexright] = temp;
}
//recursive sorting to sort the sublists
sortpoints(distances, firstindex, indexpivot - 1, data);
sortpoints(distances, indexpivot + 1, lastindex, data);
}
printpoints(data, n_points);
}
Thanks for your help, I have been trying to debug this for hours, even using a debugger.
Ouch! You call sortpoints() with i as argument. That argument, according to your prototype and code, should be the last index, and i is not the last index, but the last index + 1.
int indexleft = firstindex;
int indexright = lastindex; // indexright is pointing to a non-existent element.
int indexpivot = (int)((lastindex + 1) / 2);
int n_points = lastindex + 1;
double left = distances[indexleft];
double right = distances[indexright]; // now right is an undefined value, or segfault.
To fix that, call your sortpoints() function as:
sortpoints (0, n_points-1, data);
The problem is in your sortpoints function. The first while loop is looping infinitely. To test that is it an infinite loop or not place a printf statement
printf("Testing first while loop\n");
in your first while loop. You have to fix that.
There are quite a number of problems, but one of them is:
int indexpivot = (int)((lastindex + 1) / 2);
The cast is unnecessary, but that's trivia. Much more fundamental is that if you are sorting a segment from, say, 48..63, you will be pivoting on element 32, which is not in the range you are supposed to be working on. You need to use:
int indexpivot = (lastindex + firstindex) / 2;
or perhaps:
int indexpivot = (lastindex + firstindex + 1) / 2;
For the example range, these will pivot on element 55 or 56, which is at least within the range.
I strongly recommend:
Creating a print function similar to printpoints() but with the following differences:
Takes a 'tag' string to identify what it is printing.
Takes and prints the distance array too.
Takes the arrays and a pair of offsets.
Use this function inside the sort function before recursing.
Use this function inside the sort function before returning.
Use this function in the main function after you've read the data.
Use this function in the main function after the data is sorted.
Print key values — the pivot distance, the pivot index, at appropriate points.
This allows you to check that your partitioning is working correctly (it isn't at the moment).
Then, when you've got the code working, you can remove or disable (comment out) the printing code in the sort function.

Passing a 2d array and using recursion error

I am doing an assignment and have trouble getting the code compiled. The code must have recursion. The idea is to pass a 2d array sequentially - row by row, column by column and to get a private helper method to match cases and return the result.
I have tried looking at different solutions and everything seems in order, however I get an error:
required: int
found: int[][]
I am passing an array, int row and int column to a method that should be accepting exactly those three.
Take a look:
public static int [][] calculateProximity ( boolean [][] mineField )
{
int [][] proximityField = new int [mineField.length][mineField[0].length];
for (int row = 0; row < mineField.length; row++) {
for (int column=0; column <mineField[row].length; column++) {
proximityField [row][column] = calculateProximity (mineField, row, column);
}
}
return proximityField;
}
private static int [][] calculateProximity (boolean [][] mineField,
int row, int column)
{
int [][] proximityField;
if (row >= mineField.length || column >= mineField[row].length){
return proximityField=0;
}
else if (mineField [row][column]= true){
proximityField[row][column]=1;
return proximityField;
}
else
{
proximityField[row][column]=0;
}
return proximityField;
}
By the way, calculateProximity main method is to return an int 2d array, but it is given a boolean 2d array.
return proximityField=0;, is incorrect. Here, you are returning the result of proximityfield=0. This is going to be a single integer, the value 0. When you assign a variable, the return value is the value you assigned to the variable. You should probably return null instead.
Never use loops while performing recursion. I hope this code gives you some idea:
#include<stdio.h>
#include<stdlib.h>
int i=0,j=0,k=0,flag=0;
int function_Matrix(int arr[][4],int i,int j)
{
if(j==4||i==3)
return 1;
if(flag==0)
{
printf("\t%d",arr[i][j]);
}
function_Matrix(arr,i,j+=1);
printf("\n");
function_Matrix(arr,i+=1,j=0);
flag=1;
}
int main()
{
int x;
int arr[][4]={{1,2,3,4},
{5,6,7,8},
{9,7,6,5}};
function_Matrix(arr,0,0);
}

Resources