A directed and weighted graph is saved in a file through the list of its edges with the following format: v1 val v2, where indicating that v1 is connected to v2 with an edge with weight val(int > 0).
This is an example of the input file
fF 1 123
A0 2 fF
A0 5 h9
h9 3 123
123 2 F2
123 4 d1
F2 3 Dd
F2 4 d1
d1 2 Dd
d1 4 xd
d1 1 h9
Dd 5 xd
xd 4 A0
F2 3 fF
I have to write a C program that:
read the file and save the graph in an appropriate data structure
after receiving two vertices v1 and v2 and two ints k and p (k<=p), print the path thath starts in v1 and ends in v2 which respects the following constraints
is maximum the sum of the weights
are re-crossed at least k vertices
the complessive number of the re-crossing is at least p
the path ends when it arrives on the destination vertex
I solved the first point but I have no idea for the second. This is all the code I wrote:
main.c
#include <stdio.h>
#include <stdlib.h>
#include "graph.h"
void main() {
int k = 1, p = 1;
char v1[21], v2[21];
graph_t G = GRAPHread("file.txt");
printf("Insert 2 vertex");
scanf("%s %s", v1, v2);
GRAPHfindPath(G, k, p, v1, v2);
}
edge.h
#ifndef EDGE_H
#define EDGE_H
typedef struct edge_s { int v; int w; int wt; } edge_t;
edge_t EDGEcreate(int v, int w, int wt);
#endif
edge.c
#include "edge.h"
edge_t EDGEcreate(int v, int w, int wt) {
edge_t e;
e.v = v;
e.w = w;
e.wt = wt;
return e;
}
ST.h
#ifndef ST_H
#define ST_H
typedef struct symbletable_s *st_t;
int STinsert(st_t st, char *key);
int STsearch(st_t st, char *k);
st_t STinit(int maxN);
#endif
ST.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "ST.h"
struct symbletable_s { char **a; int M; };
st_t STinit(int maxN) {
int i;
st_t st = malloc(sizeof(*st));
st->M = maxN;
st->a = malloc(sizeof(char *)*st->M);
return st;
}
int hash(char *k, int M) {
int h = 0, base = 127;
for (; *k != '\0'; k++) h = (base*h + *k) % M;
return h;
}
int full(st_t st, int i) {
if (st->a[i] == NULL) return 1;
return 0;
}
int STinsert(st_t st, char *key) {
int i = hash(key, st->M);
while (full(st,i))
i = (i + 1) % st->M;
st->a[i] = malloc(sizeof(char)*(strlen(key) + 1));
memcpy(st->a[i], key, strlen(key) + 1);
return i;
}
int STsearch(st_t st, char *k) {
int i = hash(k, st->M);
while (full(st, i)) {
if (strcmp(k, st->a[i]) == 0) return i;
else i = (i + 1) % st->M;
}
return -1;
}
graph.h
#ifndef GRAPH_H
#define GRAPH_H
typedef struct graph_s *graph_t;
graph_t GRAPHread(char *s);
void GRAPHfindPath(graph_t G, int k, int p, char *v1, char *v2);
#endif
graph.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "graph.h"
#include "ST.h"
#include "edge.h"
#define MAX 21
typedef struct node_s *link;
struct node_s { int v; int wt; link next; };
struct graph_s {
int V;
int E;
link *adj_l;
link z;
st_t tab;
};
link NEW(int v, int wt, link next) {
link x = malloc(sizeof *x);
x->v = v;
x->next = next;
x->wt = wt;
return x;
}
graph_t GRAPHinit(int V) {
int v;
graph_t G = malloc(sizeof *G);
G->V = V; G->E = 0; G->z = NEW(-1, -1, NULL);
G->adj_l = malloc(G->V*sizeof(link));
for (v = 0; v < G->V; v++)
G->adj_l[v] = G->z;
G->tab = STinit(V);
return G;
}
void insertE(graph_t G, edge_t e) {
int v = e.v, w = e.w, wt = e.wt;
G->adj_l[v] = NEW(w, wt, G->adj_l[v]);
G->adj_l[w] = NEW(v, wt, G->adj_l[w]);
G->E++;
}
graph_t GRAPHread(char *s) {
graph_t G;
char src[MAX], dst[MAX];
char v1[MAX], v2[MAX];
int nE = 0, i, i1, i2, wt;
FILE *fp = fopen(s, "r");
while (fscanf(fp, "%*s %*d %*s") != EOF)
nE++;
rewind(fp);
G = GRAPHinit(nE * 2);
for (i = 0; i < nE; i++) {
fscanf(fp, "%s %d %s", src, &wt, dst);
i1 = STinsert(G->tab, src);
i2 = STinsert(G->tab, dst);
insertE(G, EDGEcreate(i1, i2, wt));
}
fclose(fp);
return G;
}
void GRAPHfindPath(graph_t G, int k, int p, char *v1, char *v2) {
}
Related
I have this code which is basically some logical gates and I want the user to give the input values and just the program to print the output.The problem is I wnat two gates to have the same inputs and so I want to give the same values to funcs_ptr[3]->in2 and
funcs_ptr[4]->in1.
#include <stdio.h>
#include <stdlib.h>
typedef int (*CallBack)(int, int);
int myand (int a, int b);
int myor(int a, int b);
int mynand (int a, int b);
int mynor(int a, int b);
int myxor(int a, int b);
typedef struct gate
{
CallBack f;
struct gate * in1 ;
struct gate * in2 ;
} Gate;
int getinput()
{
int x;
scanf("%d", &x);
return x;
}
Gate * creategate(CallBack f)
{
Gate * temp ;
temp = malloc(sizeof (Gate));
temp->f = f;
temp->in1 = NULL;
temp->in2 = NULL;
return temp;
}
int eval(Gate *x)
{
int a, b;
if (x->in1 != NULL)
a = eval(x->in1);
if (x->in2 != NULL)
b = eval(x->in2);
if (x->in1==NULL && x->in2 == NULL)
return (x->f)(0,0);
else
return (x->f)(a,b);
}
int main( )
{
int i;
CallBack funcs[] = {mynor, myand, myor, mynand, myxor};
Gate * funcs_ptr[6 ], * inputs_ptr[6];
for(i=0;i<5;i++)
funcs_ptr[i] = creategate(funcs[i]);
for(i=0;i<6;i++)
inputs_ptr[i] = creategate(getinput);
for(i=0;i<3;i++)
{
funcs_ptr[i]->in1 = inputs_ptr[i];
funcs_ptr[i]->in2 = inputs_ptr[i+1];
}
funcs_ptr[3] = creategate(funcs[3]);
funcs_ptr[3]->in1 = funcs_ptr[0];
/*--*/funcs_ptr[3]->in2 = funcs_ptr[1];
funcs_ptr[4] = creategate(funcs[4]);
/*--*/funcs_ptr[4]->in1 = funcs_ptr[1];
funcs_ptr[4]->in2 = funcs_ptr[2];
funcs_ptr[5] = creategate(funcs[3]);
funcs_ptr[5]->in1 = funcs_ptr[3];
funcs_ptr[5]->in2 = funcs_ptr[4];
printf(">>>%d\n", eval(funcs_ptr[5]));
return 0;
}
int myand (int a, int b)
{
return a * b;
}
int myor(int a, int b)
{
return a+b>0;
}
int mynand (int a, int b)
{
return myand(a,b)==0;
}
int mynor(int a, int b)
{
return myor(a,b)==0;
}
int myxor(int a, int b)
{
if(a!=b) return 1;
return 0;
}
But when I run the code the eval function calls getinput() two times instead of just passing the same value.
How can I pass the same value to both structs?
Input.txt :
1. M 17 160 13.24
2. M 18 177 13.22
3. M 15 162 14.78
4. F 16 169 15.55
5. F 16 161 14.73
6. F 16 160 10.80
7. M 14 192 15.65
8. F 18 197 12.41
I am now having trouble with the function
(this function was given by the teacher)
void calculateAverages(double *dAvHeight, double *dAvAge, double *dAvTime, Student_t *pStudents, int iNumberOfLines);
I can only define dAvHeight dAvAge dAvTime as Ints, however later on i need to change them to float to calculate averages. Can anyone explain how i do that while keep using dAvHeight dAvAge dAvTime.
My question is why can i only define the averages as int if in the function it says double? does the function change the format?
Thanks again
Here is the updated code:
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <string.h>
int iNumberOfLines = 1;
int dAvHeight = 0, dAvAge = 0, dAvTime = 0;
typedef struct {
int ignore;
char Gender;
int Age;
int Height;
float Time;
} Student_t;
int determineNumberOfLines(FILE *pInputFile);
void readInputData(FILE *pInputFile, int iNumberOfLines, Student_t *pStudents);
void calculateAverages(double *dAvHeight, double *dAvAge, double *dAvTime, Student_t *pStudents, int iNumberOfLines);
// Student_t* searchFastest(Student_t *pStudents, int iNumberOfLines);
// void printToConsole(Student_t *pFastestStudent, double dAvHeight, double dAvAge, double dAvTime);
int main(int argc, char *argv[]) {
FILE *pInputFile = fopen ("resources/Input.txt", "r");
if (pInputFile == NULL){
printf("Fehler beim Öffnen");
return -1;
}
determineNumberOfLines(pInputFile);
//printf("LINES: %d\n",determineNumberOfLines(pInputFile));
Student_t pStudents[iNumberOfLines];
//printf("%d", iNumberOfLines);
readInputData(pInputFile, iNumberOfLines, pStudents);
calculateAverages(dAvHeight, dAvAge, dAvTime, pStudents, iNumberOfLines);
return 0;
}
int determineNumberOfLines(FILE *pInputFile){
fopen ("resources/Input.txt", "r");
int ch;
while(!feof(pInputFile))
{
ch = fgetc(pInputFile);
if(ch == '\n')
{
iNumberOfLines++;
}
}
fclose(pInputFile);
return iNumberOfLines;
}
void readInputData(FILE *pInputFile, int iNumberOfLines, Student_t *pStudents){
fopen ("resources/Input.txt", "r");
int i = 0;
char buffer [120];
while (fgets(buffer, sizeof buffer, pInputFile) != 0)
{
if (sscanf(buffer, "%d. %c %d %d %f", &pStudents[i].ignore, &pStudents[i].Gender, &pStudents[i].Age, &pStudents[i].Height, &pStudents[i].Time) <= sizeof buffer)
{
i++;
}
}
fclose(pInputFile);
}
void calculateAverages(double *dAvHeight, double *dAvAge, double *dAvTime, Student_t *pStudents, int iNumberOfLines){
int i;
int sumHeight = 0;
int sumAge = 0;
float sumTime = 0;
for (i = 0; i <= (iNumberOfLines-1); i++){
sumHeight = sumHeight + pStudents[i].Height;
}
dAvHeight = sumHeight/ iNumberOfLines;
printf("Average Height is = %.2f \n", dAvHeight);
for (i = 0; i<= (iNumberOfLines-1); i++){
sumAge = sumAge + pStudents[i].Age;
}
//dAvAge = sumAge/iNumberOfLines;
printf("Average Age is = %.2f \n", dAvAge);
for (i = 0; i<= (iNumberOfLines-1); i++){
sumTime = sumTime + pStudents[i].Time;
}
//dAvTime = sumTime/iNumberOfLines;
printf("Average Time is = %.2f \n", dAvTime);
}
If you replace:
dAvHeight = sumHeight/ iNumberOfLines;
with this:
*dAvHeight = (double)sumHeight / iNumberOfLines;
Than that should do the trick. You would also have to do something similar to the lines you commented out.
The asterisk is to make sure you are writing to the place where the pointer is pointing and the (double) is in place because otherwise it would first do the division and then the conversion, which could for exmple lead to:
(double)(5 / 2) = (double)2 = 2.0
instead of
(double)5 / 2 = 5.0 / 2 = 2.5
I resolved it by adding
double *dAvHeight;
dAvHeight = malloc(sizeof(dAvHeight));
double *dAvAge;
dAvAge = malloc(sizeof(dAvAge));
double *dAvTime;
dAvTime = malloc(sizeof(dAvTime));
in the main function and removing the int declarations in the start
and by doing what S3gfault suggested
Thanks !
I'm trying to create a extended binary tree in a main function with finite number of nodes.
The problem is that compliler keeps showing
error: incopatible types when assigning to type 'struct node' from type 'int'
This is my code:
#include <stdio.h>
#include <stdlib.h>
#define NULLitem (-1)
typedef struct node * link;
struct node {
int item;
link l;
link r;
}
link NEW (int item, link l, link r)
{
link x = malloc(sizeof * x);
x->item = item;
x->l = l;
x->r = r;
return x;
}
void Tprint(link p, int indent)
{
int i;
if (p!=NULL){
Tprint(p->r, indent+4);
for(i=0; i<indent; i++)
printf(" ");
printf("%d\n", p->item);
Tprint(p->l,indent+4);
}
}
int main(void)
{
link T, M, N, z, Root;
z = NEW(NULLitem,NULL,NULL);
Root->item = 6;
T = NEW(5, NULL, NULL);
Root->l = T;
M = NEW(7, NULL, NULL);
Root->r = M;
M->l= NEW(NULLitem, NULL, NULL);
M->r= NEW(9,z,z);
N = NEW(2,z,z);
T->l = N;
T->r = NEW(NULLitem,NULL, NULL);
Tprint(Root,3);
return 0;
}
The error is on line 12 (the compiler says it all), "Pointer from integer without cast" is a warning which will disappear if you correct the error on line 12 of your program.
You actually forgot the semicolon here at:
struct node { int item;
link l;
link r;
}
Write a semicolon after the braces, your program should be like:
#include <stdio.h>
#include <stdlib.h>
#define NULLitem (-1)
typedef struct node * link;
struct node { int item;
link l;
link r;
};
link NEW (int item, link l, link r){
link x = malloc(sizeof * x);
x->item = item;
x->l = l;
x->r = r;
return x;
}
void Tprint(link p, int indent){
int i;
if (p!=NULL){
Tprint(p->r, indent+4);
for(i=0; i<indent; i++)
printf(" ");
printf("%d\n", p->item);
Tprint(p->l,indent+4);
}
}
int main(void)
{
link T, M, N, z, Root;
z = NEW(NULLitem,NULL,NULL);
Root->item = 6;
T = NEW(5, NULL, NULL);
Root->l = T;
M = NEW(7, NULL, NULL);
Root->r = M;
M->l= NEW(NULLitem, NULL, NULL);
M->r= NEW(9,z,z);
N = NEW(2,z,z);
T->l = N;
T->r = NEW(NULLitem,NULL, NULL);
Tprint(Root,3);
return 0;
}
The output would be like:
-1
9
-1
7
-1 6
-1
5
-1
2
-1
Runs without any errors.
I need to put inside an array, the values of a binary tree, but the thing is, I should only put inside the array the values that are at a certain depth. And it should output the number of elements inserted at the array.
I have made this:
int nivel2_(ABin a, int n, int v[], int level, int *i){
int t;
if(!a) return 0;
if(n == level){
v[(*i)++] = a->value;
return 1;
}else{
t = nivel2_(a->left, n, v, level+1, i) + nivel2_(a->right, n, v, level+1, i);
}
return t;
}
int nivel2(ABin a, int n, int v[]){
int k = 0;
int *i;
i = &k;
return nivel2_(a, n, v, 1, i);
}
As I will keep changing the index recursively and only when we reach the depth we want, I thought of using a pointer, this way, when one part of the recursive folding happens it will change the value to all the other folding processes. Makes sense?
Structures:
typedef struct slist
{
int value;
struct slist* next;
} *SList;
typedef struct arvbin* ABin;
typedef struct arvbin
{
int value;
ABin right;
ABin left;
} arvb;
DOES IT WORK?
Only when I want the elements of the first level of depth!
Calling like this:
nivel2(tree2, 1, v);
Complete code
#include <stdio.h>
#include <stdlib.h>
typedef struct slist
{
int value;
struct slist* next;
} *SList;
typedef struct arvbin* ABin;
typedef struct arvbin
{
int value;
ABin right;
ABin left;
} arvb;
int nivel2_(ABin a, int n, int v[], int level, int *i){
int t;
if(!a) return 0;
if(n == level){
v[(*i)++] = a->value;
return 1;
}else{
t = nivel2_(a->left, n, v, level+1, i) + nivel2_(a->right, n, v, level+1, i);
}
return t;
}
int nivel2(ABin a, int n, int v[]){
int k = 0;
int *i;
i = &k;
return nivel2_(a, n, v, 1, i);
}
void insertTree(ABin *tree, int val){
if((*tree)==NULL){
*tree = (ABin) malloc(sizeof(arvb));
(*tree)->value = val;
(*tree)->left = NULL;
(*tree)->right = NULL;
return;
}
else if(val > (*tree)->value)
{
insertTree(&((*tree)->right), val);
}
else if(val <= (*tree)->value)
{
insertTree(&((*tree)->left), val);
}
return;
}
int main(){
int v[10] = {0};
ABin tree2 = NULL;
insertTree(&tree2, 22);
insertTree(&tree2, 1);
insertTree(&tree2, 3);
nivel2(tree2, 1, v);
int i;
for(i=0; i<5; i++){
printf("%d\n", v[i]);
}
return 0;
}
The code looks mostly OK to me. Here's a mildly modified version, mainly with a tree printing function added, and some diagnostics, and an extended tree. My suspicion is that you expected your tree to have just 2 levels, but it actually had 3.
Code
#include <stdio.h>
#include <stdlib.h>
typedef struct slist
{
int value;
struct slist* next;
} *SList;
typedef struct arvbin* ABin;
typedef struct arvbin
{
int value;
ABin right;
ABin left;
} arvb;
static int nivel2_(ABin a, int n, int v[], int level, int *i)
{
int t = 0;
if (a)
{
if (n == level)
{
v[(*i)++] = a->value;
t = 1;
}
else
{
t += nivel2_(a->left, n, v, level + 1, i);
t += nivel2_(a->right, n, v, level + 1, i);
}
}
return t;
}
static int nivel2(ABin a, int n, int v[])
{
int k = 0;
int r = nivel2_(a, n, v, 1, &k);
printf("r = %d; k = %d\n", r, k);
return k;
}
static
void insertTree(ABin *tree, int val)
{
if ((*tree) == NULL)
{
*tree = (ABin) malloc(sizeof(arvb));
(*tree)->value = val;
(*tree)->left = NULL;
(*tree)->right = NULL;
return;
}
else if (val > (*tree)->value)
{
insertTree(&((*tree)->right), val);
}
else if (val <= (*tree)->value)
{
insertTree(&((*tree)->left), val);
}
}
static void tree_to_array(ABin tree, int level)
{
int v[10] = { 0 };
int n = nivel2(tree, level, v);
printf("Converted level %d to array:", level);
for (int i = 0; i < n; i++)
printf(" %d", v[i]);
putchar('\n');
}
static void print_tree(ABin tree, int level)
{
if (tree != 0)
{
printf("Level %d: %d\n", level, tree->value);
print_tree(tree->left, level + 1);
print_tree(tree->right, level + 1);
}
}
int main(void)
{
ABin tree2 = NULL;
insertTree(&tree2, 22);
insertTree(&tree2, 10);
insertTree(&tree2, 13);
insertTree(&tree2, 33);
insertTree(&tree2, 39);
insertTree(&tree2, 43);
insertTree(&tree2, 19);
print_tree(tree2, 1);
for (int level = 1; level < 5; level++)
tree_to_array(tree2, level);
return 0;
}
Sample output
Level 1: 22
Level 2: 10
Level 3: 13
Level 4: 19
Level 2: 33
Level 3: 39
Level 4: 43
r = 1; k = 1
Converted level 1 to array: 22
r = 2; k = 2
Converted level 2 to array: 10 33
r = 2; k = 2
Converted level 3 to array: 13 39
r = 2; k = 2
Converted level 4 to array: 19 43
That looks correct to me for the tree shape that's printed.
I'm learning heap sort by Cormen.
When I'm trying to run heapsort on the array, there's a problem and the program crashes (segmentation fault). I tried to put some printf's in the heapsort function and printing the h->size and h->count values but they seem to changed in some way from 10 to 3 (!!!) without me touching them (try to print them before the loop in heap_sort and after)..
I really don't understand what is the problem. please help me.
using Eclipse on windows7.
main.c:
#include <stdio.h>
#include "heap.h"
void print_array2(int *a, int n)
{
int *end = a + n;
while (a < end)
printf("%d ", *a++);
printf("\n");
}
int main(void)
{
int a[] =
{ 4, 1, 3, 2, 16, 9, 10, 14, 8, 7 };
print_array2(a, 10);
heapsort(a, 10);
print_array2(a, 10);
return 0;
}
heap.c:
#include <stdlib.h>
#include <stdio.h>
#include "heap.h"
void heapify(heap *h, int i)
{
int largest, left = LEFT(i), right = RIGHT(i);
if (left < h->count && (*(h->a + left) > *(h->a + i)))
largest = left;
else
largest = i;
if (right < h->count && (*(h->a + right) > *(h->a + largest)))
largest = right;
if (largest != i)
{
swap(h->a + i, h->a + largest);
heapify(h, largest);
}
}
heap *build_heap(int *a, int size)
{
heap h = (heap
)
{ .size = size, .count = size, .a = a };
heap *ph = &h;
int i = size / 2;
while (i >= 0)
heapify(ph, i--);
return ph;
}
void heapsort(int *a, int size)
{
heap *h = build_heap(a, size);
int i;
for (i = h->size - 1; i >= 1; --i)
{
swap(h->a, h->a + i);
h->count--;
heapify(h, 0);
}
}
void print_heap(heap *h)
{
int *end = h->a + h->count, *arr = h->a;
while (arr < end)
printf("%d ", *arr++);
printf("\n");
}
void print_array(heap *h)
{
int *end = h->a + h->size, *arr = h->a;
while (arr < end)
printf("%d ", *arr++);
printf("\n");
}
static void swap(int *a, int *b)
{
int temp = *a;
*a = *b;
*b = temp;
}
heap.h:
#ifndef HEAP_H_
#define HEAP_H_
typedef struct
{
int size; //array size
int count; //heap size
int *a; //int array
} heap;
#define PARENT(x) ((x + 1) / 2)
#define LEFT(x) (2 * (x) + 1)
#define RIGHT(x) (2 * ( (x) + 1) )
void heapify(heap* h, int i);
heap *build_heap(int *a, int size);
void heapsort(int *a, int size);
void print_heap(heap *h);
void print_array(heap *h);
static void swap(int *a, int *b);
#endif /* HEAP_H_ */
#mafso is correct. I changed build_heap to return a copy of the heap instead of a pointer and it worked. Maybe not the best way but it works. Here is the code:
heap.h
#ifndef HEAP_H_
#define HEAP_H_
typedef struct
{
int size; //array size
int count; //heap size
int *a; //int array
} heap;
#define PARENT(x) ((x + 1) / 2)
#define LEFT(x) (2 * (x) + 1)
#define RIGHT(x) (2 * ( (x) + 1) )
void heapify(heap* h, int i);
heap build_heap(int *a, int size);
void heapsort(int *a, int size);
void print_heap(heap *h);
void print_array(heap *h);
static void swap(int *a, int *b);
#endif /* HEAP_H_ */
heap.c
#include <stdlib.h>
#include <stdio.h>
#include "heap.h"
void heapify(heap *h, int i)
{
int largest, left = LEFT(i), right = RIGHT(i);
if (left < h->count && (*(h->a + left) > *(h->a + i)))
largest = left;
else
largest = i;
if (right < h->count && (*(h->a + right) > *(h->a + largest)))
largest = right;
if (largest != i)
{
swap(h->a + i, h->a + largest);
heapify(h, largest);
}
}
heap build_heap(int *a, int size)
{
heap h;// = (heap) { .size = size, .count = size, .a = a };
h.size = size;
h.count = size;
h.a = a;
heap *ph = &h;
int i = size / 2;
while (i >= 0)
heapify(ph, i--);
return *ph;
}
void heapsort(int *a, int size)
{
heap h = build_heap(a, size);
int i;
for (i = h.size - 1; i >= 1; --i)
{
swap(h.a, h.a + i);
h.count--;
heapify(&h, 0);
}
}
void print_heap(heap *h)
{
int *end = h->a + h->count, *arr = h->a;
while (arr < end)
printf("%d ", *arr++);
printf("\n");
}
void print_array(heap *h)
{
int *end = h->a + h->size, *arr = h->a;
while (arr < end)
printf("%d ", *arr++);
printf("\n");
}
static void swap(int *a, int *b)
{
int temp = *a;
*a = *b;
*b = temp;
}
This was my output:
4 1 3 2 16 9 10 14 8 7
1 2 3 4 7 8 9 10 14 16