issue in making Queue data structure as array implementation - c

this code to make simple queue data structure as array implementation
#include <stdio.h>
#define Q_MAX_SIZE 255
#include <stdbool.h>
struct queue
{
int* pointer;
int* currentValue;
int max, count, theQueue[Q_MAX_SIZE];
};
void initQueue(struct queue*);
bool pushQueue(struct queue*, int);
int* popQueue(struct queue*);
int main(void)
{
int i, j, num = 0;
struct queue obj[5];
for(i=0; i<5; i++)
{
initQueue(&obj[i]);
for(j = 0; j<3; j++)
{
num++;
pushQueue(&obj[i], num);
}
num = 0;
}
for(i=0; i<5; i++)
{
printf("Queue[%d]:\n", i);
int* inputobj;
inputobj = popQueue(&obj[i]);
while(inputobj != NULL)
{
printf("Queue[No.%d] = %d\n", i, *inputobj);
inputobj = popQueue(&obj[i]);
}
putchar('\n');
}
puts("done..!");
return 0;
}
//#################################
void initQueue(struct queue *Q)
{
Q->pointer = Q->theQueue;
Q->max = Q_MAX_SIZE;
Q->count = 0;
}
bool pushQueue(struct queue *Q, int input)
{
if(Q->count < Q->max)
{
*Q->pointer = input;
Q->pointer++;
Q->count++;
return 1;
}
else
return 0;
}
//#################################
int* popQueue(struct queue *Q)
{
int i;
if(Q->count > 0)
{
Q->currentValue = Q->theQueue;
Q->pointer--;
Q->count--;
for(i=0; i < Q->count; i++)
{
int* currentPtr = Q->theQueue + i;
int* nextPtr = currentPtr + 1;
*currentPtr = *nextPtr;
}
return Q->currentValue;
}
else
NULL;
}
there is a problem with the code in the function popQueue() in this line:
Q->currentValue = Q->theQueue;
it is work put the output is not correct
output:
Queue[0]:
Queue[No.0] = 2
Queue[No.0] = 3
Queue[No.0] = 3
Queue[1]:
Queue[No.1] = 2
Queue[No.1] = 3
Queue[No.1] = 3
Queue[2]:
Queue[No.2] = 2
Queue[No.2] = 3
Queue[No.2] = 3
Queue[3]:
Queue[No.3] = 2
Queue[No.3] = 3
Queue[No.3] = 3
Queue[4]:
Queue[No.4] = 2
Queue[No.4] = 3
Queue[No.4] = 3
done..!
but after i change the pointer (currentValue) in the queue struct to make it of type integer and edit some lines in the function popQueue() every thing work fine.
--here is the function after editing:
int* popQueue(struct queue *Q)
{
int i;
if(Q->count > 0)
{
Q->currentValue = Q->theQueue[0];
Q->pointer--;
Q->count--;
for(i=0; i < Q->count; i++)
{
int* currentPtr = Q->theQueue + i;
int* nextPtr = currentPtr + 1;
*currentPtr = *nextPtr;
}
return &Q->currentValue;
}
-- and this is the correct output:
Queue[0]:
Queue[No.0] = 1
Queue[No.0] = 2
Queue[No.0] = 3
Queue[1]:
Queue[No.1] = 1
Queue[No.1] = 2
Queue[No.1] = 3
Queue[2]:
Queue[No.2] = 1
Queue[No.2] = 2
Queue[No.2] = 3
Queue[3]:
Queue[No.3] = 1
Queue[No.3] = 2
Queue[No.3] = 3
Queue[4]:
Queue[No.4] = 1
Queue[No.4] = 2
Queue[No.4] = 3
The Question is: what makes the first code provide wrong output?

What gave you the wrong output in the first case was the fact that the pointer Q->currentValue never changed its value (the address which it was holding). It was always pointing to the first element in the queue.
Say the queue contained {1, 2, 3 |,<garbage>}.
That means, that after the first pop, the queue became:
{2, 3 |, 3, <garbage>}
and currentValue still held the address of the first element in the array, which is 2.
After the second pop:
{3 |, 3, 3, <garbage>}
and currentValue points to the first element, which value is 3,
The last time, the array is unchanged (as Q->count-- changes Q->count's value to 0), so the conent is
{| 3, 3, 3, <garbage>}
and currentValue is still pointing to a 3.
I assume that you changed the second example to make Queue->currentValue an int.
This way, it retains the original first element (which is popped).
That makes your prints work properly in your test case.
However,
Your implementation will fail if you had a 0 in your queue.
Your implementation adds needless complexity to the pop operation (O(n)). It would be much better to implement a cyclic queue, with head and tail.
Retaining a copy of the popped element in order to return it would not be my first choice. I would suggest implementing an isEmpty() method, check its result in the while loop and while the queue is not empty, simply have pop() return the queue advance its head and return the previous head element.

Related

How to fix setting ending node in a linked list created by malloc causes a segmentation fault?

I am learning dynamic memory management and am working on a program that lets you set the size of the array, and then generates it, and prints it out.
here is the code:
#include <stdio.h>
#include <stdlib.h>
typedef struct node{
int number;
struct node *next;
}node;
int main(void)
{
node *ptr;
int n, i;
printf("How big should the array initially be? ");
//scanf("%i",&n);
printf("\n\n");
// for debugging purposes
n = 8;
ptr = (node *)malloc(n * sizeof(node));
for (i = 0; i < n; i++)
{
ptr[i] = (struct node)
{
.number = i + 1,
.next = &ptr[i + 1]
};
}
struct node *listptr = &ptr[0];
ptr[n - 1].next = NULL;
/*while (listptr->next != NULL)
{
printf("ptr[%i].number = %i, ptr[%i].next->number = %i"
,i,ptr[i].number,i,ptr[i].next->number);
listptr = listptr->next;
i++;
}*/
for (i = 0; i < n; i++)
{
printf("ptr[%i].number = %i, ptr[%i].next->number = %i\n"
,i,ptr[i].number,i,ptr[i].next->number);
}
printf("How much bigger would you like this array to be? ");
printf("\n\n");
free(ptr);
}
I have tried changing malloc to calloc but I still get the same error. How do I set the ending node.next to NULL and terminate the program?
when I run the code I get this output:
How big should the array initially be?
ptr[0].number = 1, ptr[0].next->number = 2
ptr[1].number = 2, ptr[1].next->number = 3
ptr[2].number = 3, ptr[2].next->number = 4
ptr[3].number = 4, ptr[3].next->number = 5
ptr[4].number = 5, ptr[4].next->number = 6
ptr[5].number = 6, ptr[5].next->number = 7
ptr[6].number = 7, ptr[6].next->number = 8
zsh: segmentation fault ./file
In this for loop
for (i = 0; i < n; i++)
{
printf("ptr[%i].number = %i, ptr[%i].next->number = %i\n"
,i,ptr[i].number,i,ptr[i].next->number);
}
when i is equal tp n - 1 this expression ptr[i].next->number tries to access memory using the null pointer ptr[i].next.
Also in this for loop
for (i = 0; i < n; i++)
{
ptr[i] = (struct node)
{
.number = i + 1,
.next = &ptr[i + 1]
};
}
you have to write
for (i = 0; i < n; i++)
{
ptr[i] = (struct node)
{
.number = i + 1,
.next = i == n - 1 ? NULL : &ptr[i + 1]
};
}
first linked list today. This ones easy
printf(...........ptr[i].next->number);
For the last entry in the list ptr[i].next is NULL, so this fails
How to fix,
printf("ptr[%i].number = %i, ptr[%i].next->number = %i\n"
,i,ptr[i].number,i,(i == n-1)?0:ptr[i].next->number);
this prints 0 instead of crashing. Question is - what do you want to print for the last entry

How do you use malloc of struct inside a function?

In a this code,
#include <stdio.h>
#include <stdlib.h>
typedef struct test
{
int i;
double data;
} test;
void add(ar) struct test *ar;
{
int num = 10;
// *ar = malloc(num * sizeof(struct test)); // Adding this
for (int i = 0; i < num; i++)
{
ar[i].i = i;
ar[i].data = i * i;
}
}
int main(void)
{
test ar[10]; // Removing this
add(&ar);
for (int i = 0; i < 10; i++)
{
printf("%d %f\n", ar[i].i, ar[i].data);
}
return 0;
}
How do we define the struct in main but allocate the memory in the function?
I want to set the number (num) inside the function add, as it is not yet known in main.
There are two values you have to pass back from add() to main(), num and the malloc()ed array itself. As you can return only one value, there are two positilities:
a) return num and have a test ** parameter to pass back the array
int add( struct test **ar )
{
int num = 10;
*ar = malloc( num * sizeof **ar );
// initialize everything, you have to replace ar[i] by (*ar)[i]
return num;
}
call it
struct test *ar;
int num = add( &ar );
b) return the array and have a int * parameter to pass back num
struct test *add( int *num )
{
*num = 10;
struct test *ar = malloc( *num * sizeof *ar );
// initialize everything as you do now
return ar;
}
call it
int num;
struct test *ar = add( &num );
As #Bodo mentioned, either way, you have to call free( ar ); in main() when you don't need ar anymore. You could call it directly or think about having a cleanup function like free_test( struct test *ar, int num ); that does the job. Such a function is especially useful if you have more malloc()s to allocate memory for the single struct elements (eg. if they contained char * elements to store strings).
use the argument(s) to pass argument(s)
use the return value to return stuff to the caller
#include <stdio.h>
#include <stdlib.h>
struct test
{
int i;
double data;
} ;
struct test *test_create(unsigned ntest)
{
struct test *pp;
unsigned idx;
pp = malloc(sizeof *pp * ntest);
for (idx = 0; idx < ntest; idx++)
{
pp[idx].i = idx;
pp[idx].data = idx * idx;
}
return pp;
}
int main(void)
{
struct test *ptr;
ptr = test_create(10);
for (int i = 0; i < 10; i++)
{
printf("%d %f\n", ptr[i].i, ptr[i].data);
}
return 0;
}
Update: if you want to return more than a single item, you could put the items together in a struct:
#include <stdio.h>
#include <stdlib.h>
struct dope {
unsigned size;
struct {
int i;
double data;
} *array;
} ;
struct dope *dope_create(void)
{
struct dope *pp;
unsigned omg =10;
pp = malloc(sizeof *pp );
pp->array = malloc(sizeof *pp->array * omg);
pp->size = omg;
for (omg = 0; omg < pp->size; omg++)
{
pp->array[omg].i = omg;
pp->array[omg].data = omg * omg;
}
return pp;
}
int main(void)
{
struct dope *ptr;
ptr = dope_create();
for (int iii = 0; iii < ptr->size; iii++)
{
printf("%d %f\n", ptr->array[iii].i, ptr->array[iii].data);
}
return 0;
}
You have already good answers as alternatives. Anyway I will show you code for 2 common ways of writing this.
As I see in your code, the factory function will determine the actual number of structs test to allocate. I will in the example:
generate a random number of structs, using rand() since it makes no difference here
fill them in like (1,1.01), (2,2.02) ... just to have a known value for testing
show the structs' contents on screen
free() them at exit
assume that can also be 0 structures created
1: use a NULL-terminated sequence of pointers
As it is used with success in all C strings :) we can use it here. As in strings (C strings), you need to search for the terminator in order to get the array size (Of course you can set the first pointer apart for the size, Pascal-like). It can or can not be of importance to know before-hand the # of structs.
Test** add_vector()
{
// returns a null terminated array of pointers
// to 'Test', pointing to actual instances of
// 'Test', allocated and numbered with 'i' starting
// at 1 and 'data' starting at 1.01
int num = rand() % 10; // 0 to 9 Test
fprintf(stderr,
"add_vector(): creating %d structs\n", num);
// at least one pointer, the terminating one
Test** ar = (Test**)malloc((1 + num) * sizeof(Test*));
int ix = 0;
for (ix = 0; ix < num; ix += 1)
{
ar[ix] = (Test*)malloc(sizeof(Test));
// sets up ar[i] to a known value
ar[ix]->i = 1 + ix;
ar[ix]->data = 1 + ix + (1 + ix) / 100.;
}; // for()
ar[ix] = NULL; // the terminator one, as in strings
return ar;
}
To use it you just call
Test** vector = add_vector();
as you see in the example below. A single pointer is returned. No need for arguments. If the number of structs is zero a single pointer is returned, like it would be with an empty string.
The # of structs is defined inside the function, and all structs instances are allocated and numbered before returning to caller.
2: return a pointer to a struct
typedef struct
{
int i;
double data;
} Test;
typedef struct
{
unsigned size;
Test* test;
} V_Test;
V_Test* add_struct();
The allocation function returns a pointer to a V_Test struct, that contains an array of Test strucs and a size elements, an in main() for every C program
int main(in argc, char** argv)
Here is the code:
V_Test* add_struct()
{
// returns a vector of structs inside V_Test,
// with known 'size', like in main( int,char**)
// The structs are initialized with 'i' starting
// at 1 and 'data' starting at 1.01
unsigned num = rand() % 10; // 0 to 9 Test
fprintf(stderr, "add_struct(): creating %d structs\n", num);
V_Test* v = (V_Test*) malloc(sizeof(V_Test));
v->size = num;
if (num == 0)
{
v->test = NULL;
return v;
};
v->test = (Test*)malloc(num * sizeof(Test));
for (unsigned ix = 0; ix < num; ix += 1)
{
v->test[ix].i = 1 + ix;
v->test[ix].data = 1 + ix + (1 + ix) / 100.;
}; // for()
return v;
}
To used it you just call
V_Test* vector = add_struct();
And here also there are no arguments. A new V_Test is allocated and returned.
Also here the # of structs is defined inside the function, and all structs instances are allocated and numbered before returning to caller.
In the code you will see a way of use both functions, create the structs, fill them in, display the contents and release the allocated memory.
Example output
add_vector(): creating 9 structs
# 1: [1, 1.01]
# 2: [2, 2.02]
# 3: [3, 3.03]
# 4: [4, 4.04]
# 5: [5, 5.05]
# 6: [6, 6.06]
# 7: [7, 7.07]
# 8: [8, 8.08]
# 9: [9, 9.09]
9 records were created
9 records were free()'d
add_struct(): creating 4 structs
# 1: [1, 1.01]
# 2: [2, 2.02]
# 3: [3, 3.03]
# 4: [4, 4.04]
4 records were created
4 records were free()'d
C Code
I compiled just once under MSVC.
#include <stdio.h>
#include <stdlib.h>
typedef struct
{
int i;
double data;
} Test;
typedef struct
{
unsigned size;
Test* test;
} V_Test;
V_Test* add_struct();
Test** add_vector();
void as_vector_of_pointers();
void as_struct_of_struct();
int main(void)
{
srand(210728);
as_vector_of_pointers();
as_struct_of_struct();
return 0;
}
Test** add_vector()
{
// returns a null terminated array of pointers
// to test
int num = rand() % 10; // 0 to 9 Test
fprintf(stderr,
"add_vector(): creating %d structs\n", num);
// at least one pointer, the terminating one
Test** ar = (Test**)malloc((1 + num) * sizeof(Test*));
int ix = 0;
for (ix = 0; ix < num; ix += 1)
{
ar[ix] = (Test*)malloc(sizeof(Test));
// sets up ar[i] to a known value
ar[ix]->i = 1 + ix;
ar[ix]->data = 1 + ix + (1 + ix) / 100.;
}; // for()
ar[ix] = NULL; // the terminator one, as in strings
return ar;
}
V_Test* add_struct()
{
// returns a vector of structs inside V_Test,
// with known 'size', like in
// main( int,char**)
unsigned num = rand() % 10; // 0 to 9 Test
fprintf(stderr, "add_struct(): creating %d structs\n", num);
V_Test* v = (V_Test*) malloc(sizeof(V_Test));
v->size = num;
if (num == 0)
{
v->test = NULL;
return v;
};
v->test = (Test*)malloc(num * sizeof(Test));
for (unsigned ix = 0; ix < num; ix += 1)
{
v->test[ix].i = 1 + ix;
v->test[ix].data = 1 + ix + (1 + ix) / 100.;
}; // for()
return v;
}
void as_struct_of_struct()
{
V_Test* vector = add_struct();
if (vector->size == 0)
{
printf("No records were created!\n");
free(vector);
return;
}
for ( unsigned count = 0; count < vector->size; count+=1)
{
printf("#%3d: [%d, %.2f]\n",
1 + count,
vector->test[count].i,
vector->test[count].data
);
}; // for()
printf("%d records were created\n", vector->size);
// to free() vector:
free(vector->test);
printf("%d records were free()'d\n", vector->size);
free(vector);
return;
};
void as_vector_of_pointers()
{
Test** vector = add_vector();
// now test the vector to count the number of
// records generated in the funcion
if (vector[0] == NULL)
{
printf("No records were created!\n");
free(vector);
return;
}
unsigned count = 0;
while (vector[count] != NULL)
{
printf("#%3d: [%d, %.2f]\n", 1 + count, (vector[count])->i,
(vector[count])->data);
count += 1;
};
printf("%d records were created\n", count);
// to free() vector, same way:
for (unsigned i = 0; i < count; i += 1) free(vector[i]);
free(vector);
printf("%d records were free()'d\n", count);
return;
}
SO vigilants: I always cast malloc() pointers, as I reminder to
myself and others reading the code. No implicit conversions. No need to pointing that.

Min Heap Problem After Extracting Minimum Element

I'm working on a min heap implementation and am really new to the concept.
Using this as reference:
https://www.geeksforgeeks.org/building-heap-from-array/
https://algorithmtutor.com/Data-Structures/Tree/Binary-Heaps/
I modified the code and came up with:
(this is the code I'm having problems with, all other code is irrelevant to my problem, at least so I think)
#define LCHILD(x) (2 * (x)) + 1
#define RCHILD(x) (2 * (x)) + 2
#define PARENT(x) ((x) - 1) / 2
typedef struct {
int key;
Event *element; // Assume NULL for this example
} Node;
void swap(Node **x, Node **y) {
Node *temp = *x;
*x = *y;
*y = temp;
}
void heapify(void *pq, int n, int i) {
Node **node = (Node**) pq;
int smallest = i; // Initialize smallest as root
int left = LCHILD(i);
int right = RCHILD(i); // right = 2*i + 2
if (left < n && (node[left])->key < (node[smallest ])->key)
smallest = left;
if (right < n && (node[right])->key < (node[smallest ])->key)
smallest = right;
if (smallest != i) {
swap(&node[i], &node[smallest ]);
heapify(node, n, smallest );
}
}
int extractKey(void *pq, int *n) {
Node **node = (Node**) pq;
int minElement = (node[0])->key;
node[0] = node[*n - 1];
*n = *n - 1;
heapify(pq, *n, 0);
return minElement;
}
void insert(void *pq, int key, void *element, int *n) {
Node **node = (Node**) pq;
node[*n]->key = key;
node[*n]->element = element;
*n = *n + 1;
int i = *n - 1;
while ( (i != 0) && (node[PARENT(i)]->key > node[i]->key) ) {
swap(&node[PARENT(i)], &node[i]);
i = PARENT(i);
}
}
int main() {
Node **pq = malloc (100 * sizeof(Node*));
int i;
for(i = 0; i < 100; i++) {
pq[i] = malloc(sizeof(Node));
pq[i]->element = malloc(sizeof(Event));
}
int n = 0; // heap size
insert(pq, 0, NULL, &n);
printHeap(pq, n);
insert(pq, 5, NULL, &n);
printHeap(pq, n);
insert(pq, 1, NULL, &n);
printHeap(pq, n);
insert(pq, 50, NULL, &n);
printHeap(pq, n);
extractKey(pq, &n);
printHeap(pq, n);
insert(pq, 10, NULL, &n);
printHeap(pq, n);
return 0;
}
OUTPUT:
Array representation of heap is:
0
Array representation of heap is:
0 5
Array representation of heap is:
0 5 1
Array representation of heap is:
0 5 1 50
Array representation of heap is:
1 5 50
Array representation of heap is:
1 5 10 10 // What happened here?
This only happens when I extract the minimum node and then add a new one. If I don't extract a node, then it works perfectly fine. Am I missing something?
EDIT 1: This is the print function I'm using. Forgot to add it in the initial post (It's a modified version from the one found here:
https://algorithmtutor.com/Data-Structures/Tree/Binary-Heaps/)
void printHeap(void *pq, int n) {
Node **node = (Node**) pq;
printf("Array representation of heap is:\n");
for (int i = 0; i < n; ++i) {
printf("%d ", node[i]->key);
}
printf("\n");
}
EDIT 2: I did some more testing. Here's what I got:
Inserted some print statements:
void insert(void *pq, int key, void *element, int *n) {
Node **node = (Node**) pq;
if(*n > 0) {
printf("node[%d] = %d\n", *n-1, node[*n-1]->key);
}
node[*n]->key = key;
printf("node[%d] = %d\n", *n, node[*n]->key);
if(*n > 0) {
printf("node[%d] = %d\n", *n-1, node[*n-1]->key);
}
node[*n]->element = element;
*n = *n + 1;
// move up until the heap property satisfies
int i = *n - 1;
while ( (i != 0) && (node[PARENT(i)]->key > node[i]->key) ) {
swap(&node[PARENT(i)], &node[i]);
i = PARENT(i);
}
}
OUTPUT:
node[0] = 0
Array representation of heap is:
0
node[0] = 0
node[1] = 5
node[0] = 0
Array representation of heap is:
0 5
node[1] = 5
node[2] = 1
node[1] = 5
Array representation of heap is:
0 5 1
node[2] = 1
node[3] = 50
node[2] = 1
Array representation of heap is:
0 5 1 50
Array representation of heap is:
1 5 50
node[2] = 50
node[3] = 10
node[2] = 10 // Huh? it should be 50
Array representation of heap is:
1 5 10 10
The problem is the line node[0] = node[*n - 1]; in extractKey. That is setting two of your node pointers to the same value, so you no longer have 100 unique node pointers. (As a consequence, it is also leaking memory.) Changing the line to swap(&node[0], &node[*n - 1]); should solve the problem.

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

Prim's Algorithm in C producing incorrect output

I've been tasked with implementing Prim's algorithm to find the MCST using an adjacency matrix to represent the graph, and a struct to hold the MCST. The program takes in a file input, applies the algorithm and then outputs the minimum cost spanning tree. I got the program to take a file input and produce output, but the values I am getting are incorrect and look like dummy values to me.
My assumption is that the error occurs in either how I am storing the file input in my array, or in the algorithm itself. I've spent a good 12-15 hours troubleshooting this issue and am hoping someone can provide insight. The program is written in C and compiled with make in the format ./a6 <file>. I take and store the file input in my main() and then the methods are used in the order they are called. Below is an example my professor provided. The first line contains info about the vertices being entered and the remaining lines contain the actual data itself.
input:
6 10 0 <<--(size, edges, start)
0 1 16 <<--(from, to, weight)
0 5 21
0 4 19
1 2 5
1 3 6
1 5 11
2 3 10
3 4 18
3 5 14
4 5 33
output:
0 1 16 <<--(first edge)
1 2 5
1 3 6
1 5 11
3 4 18
total cost: 56
My code:
#include <stdio.h>
#include <stdlib.h>
#include <limits.h> /* for INT_MAX */
#define N 10 /* max matrix size is 10 x 10 */
#define INF 9999
int cost = 0;
typedef struct lnode {
int fromv;
int tov;
int weight;
struct lnode *next;
} lnode;
int insertnode(lnode **lst, int from, int to, int wt);
void prims(int amtrx[][N],int n, lnode **lst);
void printpaths(lnode **lst);
void freelist(lnode **lst);
int isValid(int a, int b, int select[]);
int insertnode(lnode **lst, int from, int to, int wt){
lnode *newnode;
newnode = (lnode *) malloc(sizeof(struct lnode));
newnode->fromv = from;
newnode->tov = to;
newnode->weight = wt;
newnode->next=NULL;
if(*lst == NULL){
newnode -> next = *lst;
*lst = newnode;
} else {
lnode *current;
current = *lst;
while(current->next != NULL){
current = current->next;
}
newnode->next = current->next;
current->next = newnode;
}
return 1;
}
int isValid(int a, int b, int select[]){
if(a == b) return 0;
if(select[a] == 0 && select[b] == 0) return 0;
else if (select[a] == 1 && select[b] == 1) return 0;
return 1;
}
void prims(int amtrx[][N], int n, lnode **lst){
int i, j, row, col, edges_seen, min;
int select[N] = {0};
edges_seen = 0;
select[n] = 1;
while(edges_seen < N-1){
min = INF;
row = -1;
col = -1;
for(i = 0; i < N; i++) {
for(j = 0; j < N; j++){
if(amtrx[i][j] < min) {
if(isValid(i, j, select) == 1){
min = amtrx[i][j];
row = i;
col = j;
}
}
}
}
if(row != -1 && col != -1){
select[col] = 1;
select[row] = 1;
cost = cost + min;
insertnode(lst, row, col, min);
edges_seen++;
}
for(i = 0; i < N; i++){
printf("%3d", select[i]);
}
puts("\n\n");
}
}
void printpaths(lnode **lst){
lnode *current;
current = *lst;
while(current != NULL) {
printf("%4i ",current->fromv);
printf("%4i ", current->tov);
printf("%4i \n", current->weight);
current = current->next;
}
printf("\ntotal cost: %4i\n", cost);
}
void freelist(lnode **lst) {
lnode *temp = NULL;
while(*lst != NULL)
{
temp = *lst;
*lst = (*lst)->next;
free(temp);
}
}
int main(int argc, char **argv){
FILE *f = fopen(argv[1], "r");
lnode *lst;
lst = (lnode *)malloc(sizeof(struct lnode));
int i, j, nsz, nedg, fr, to, vtx, wt;
vtx = 1111;
nedg = 999;
nsz = 100;
fscanf(f, "%d %d %d", &nsz, &nedg, &vtx);
int amtrx[nsz][N];
for(i = 0; i < nsz; i++){
for(j = 0; j < nsz; j++){
amtrx[i][j] = INF;
}
}
for(i = 0; i < nedg; i++){
fscanf(f, "%d %d %d", &fr, &to, &wt);
amtrx[fr][to] = wt;
amtrx[to][fr] = wt;
}
fclose(f);
prims(amtrx, vtx, &lst);
printpaths(&lst);
freelist(&lst);
return EXIT_SUCCESS;
}

Resources