Prim's Algorithm in C producing incorrect output - c

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

Related

Converting an Adjacency Matrix to an Adjacency List in C

I am supposed to convert a given adjacency matrix to an adjacency list in C. I need this adjacency list because this is where I will implement my algorithm for Depth First Search (DFS). Before I write my code for DFS, I wanna make sure that I made the right adjacency list. However, my problem is that when I try to run my code, the program does not proceed in printing the graph. I believe it's because of how I read user inputs because that is exactly where the program stops. Now my question is, how do I read multiple inputs in one line? I tried using fgets() but my program does not proceed in printing the graph/adjacency list. Provided below is the code that I wrote.
Here are the struct nodes:
typedef struct vertexnode VertexNode;
struct vertexnode
{
int vertex;
VertexNode *Next;
};
typedef struct graph
{
int numVertices;
VertexNode **adjLists;
} Graph;
Below is the main function:
int main()
{
int size, i, temp;
//char input1[100000];
scanf("%d\n", &size); // scan number of vertices
Graph *graph = createAGraph(size);
for(i = 0; i < size; i++) // scan the adjacency MATRIX
{
char input1[100000];
int j = 0;
fgets(input1, sizeof(input1), stdin);
char *piece = strtok(input1, " "); // extract first number
while(piece != NULL)
{
temp = atoi(piece); // convert from char to int
if(temp == 1) // create new node
{
addEdge(graph, i, j); //add edge from vertex i to j
}
j++;
piece = strtok(NULL, " ");
}
}
printGraph(graph);
return 0;
}
Function for creating a vertex:
VertexNode *createVertex(int vertexNum)
{
VertexNode *new_vertex = (VertexNode *) malloc(sizeof(VertexNode));
new_vertex->vertex = vertexNum + 1;
new_vertex->Next = NULL;
return new_vertex;
}
Function for creating the graph:
Graph *createAGraph(int size)
{
Graph *graph = (Graph *)malloc(sizeof(Graph));
graph->numVertices = size;
graph->adjLists = (VertexNode **)malloc(sizeof(VertexNode *));
for(int i = 0; i < size; i++)
graph->adjLists[i] = NULL;
return graph;
}
Function for addEdge:
void addEdge(Graph *graph, int s, int d)
{
VertexNode *newNode = createVertex(d);
newNode->Next = graph->adjLists[s];
graph->adjLists[s] = newNode;
}
Function for printing the adjacency list:
void printGraph(Graph *graph)
{
for(int i = 0; i < graph->numVertices; i++)
{
VertexNode *temp = graph->adjLists[i];
printf("\n Vertex %d\n: ", i+1);
while(temp)
{
printf("%d -> ", temp->vertex);
temp = temp->Next;
}
newline;
}
}
Is there a better way of taking a user input given the context that we have to read multiple inputs in a line and there's an arbitrary number of lines?
Example Input:
4
0 0 1 0
1 0 0 1
1 1 0 1
0 1 0 0
First input is the number of vertices in the list
The succeeding lines represent the adjacency matrix
The adjacency list should be like this:
1 -> 3
2 -> 1 -> 4
3 -> 1 -> 2 -> 4
4 -> 2
Would you please try the following:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int
main()
{
int i, j, size;
char *tk; // pointer to a token
char delim[] = " "; // delimiter of tokens
char line[BUFSIZ];
int *m; // matrix
fgets(line, BUFSIZ, stdin); // read stdin and assign line
size = atoi(line); // size of matrix
if (NULL == (m = malloc(sizeof(int) * size * size))) {
// allocate a matrix
fprintf(stderr, "malloc failed\n");
exit(1);
}
for (i = 0; i < size; i++) {
if (NULL == fgets(line, BUFSIZ, stdin)) {
fprintf(stderr, "insufficient lines\n");
exit(1);
}
j = 0;
tk = strtok(line, delim);
while (tk != NULL) {
m[i * size + j] = atoi(tk); // assign element of matrix
j++;
if (j > size) {
fprintf(stderr, "too many columns\n");
exit(1);
}
tk = strtok(NULL, delim);
}
if (j < size) {
fprintf(stderr, "insufficient columns\n");
exit(1);
}
}
// print the adjacency list
for (i = 0; i < size; i++) {
printf("%d", i + 1);
for (j = 0; j < size; j++) {
if (m[i * size + j]) {
printf(" -> %d", j + 1);
}
}
printf("\n");
}
return 0;
}
As I'm not aware of your special functions such as createAGraph() or
addEdge(), I've used my own definition of matrix. Please modify
my code to meet your interfaces.

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.

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

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

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

C - binary tree: can't return correct number of pruned nodes

I need to prune a binary tree past a certain level, l and need to return the number of pruned nodes.
Here's what I got:
#include "abin.h"
int freeAB (ABin a) {
int count = 0;
if(a == NULL) return count;
count = count + freeAB(a->esq);
count = count + freeAB(a->dir);
free(a);
count++;
return count;
}
int pruneAB (ABin *a, int l) {
int count = 0;
if(l == 0){
count = count + freeAB((*a)->esq);
count = count + freeAB((*a)->dir);
(*a) = NULL;
}
else{
count = count + pruneAB(&((*a)->esq), l-1);
count = count + pruneAB(&((*a)->dir), l-1);
}
return count;
}
ABIN.H:
#include <stdio.h>
#include <stdlib.h>
typedef struct lligada {
int valor;
struct lligada *prox;
} *LInt;
typedef struct nodo {
int valor;
struct nodo *esq, *dir;
} *ABin;
int pruneAB (ABin *a, int l);
This is the output of what I should have got and what I got:
Input: (depth=2)
8
4 12
2 6 10 14
1 3 5 7 9 11 13 15
Output:
[expected] res=12
8
4 12
[obtained] res=8
8
4 12
0/10 correct answers
Interestingly, if I create something like int r = 0; and do r++; every time the if(l == 0) statement is true, and then do a print statement, it prints r 4 times.
If I added 4 to the final count I would get the correct answer. I assume that I should then add to count the number of times the if(l == 0) is true.
(I can't do it. If I do count++ I get segmentation fault)
How would you do it? Thanks.
https://codeboard.io/projects/16275
int pruneAB (ABin *a, int l) {
int count = 0;
if (!*a) return 0;
if (l < 0) return count;
if(l == 0){
count = freeAB(*a);
(*a) = NULL;
}
else{
count = count + pruneAB(&((*a)->esq), l-1);
count = count + pruneAB(&((*a)->dir), l-1);
}
return count;
}

Resources