I am a beginner at programming (and it is not my subject of discipline) and this is my first question here, apologies if I'm not posting it it properly.
I am trying a problem (in C) in which one has to define a structure for a point, take inputs of points from a file to a dynamic array, in which the first line contains the number of points, and the remaining lines contain the coordinates of the points with spaces in between. Then I have to write a function to determine the points which are non-dominated, definitions given :
• A point P1 = ( x1 , y1 ) is dominated by a point P2 = ( x2 , y2 ) if
y2 > y1 and x2 > x1
• A point is non-dominated in a set of points, if no point dominates
it in that set
And another function to determine and print the level of dominance of each point stored in the array formed. I need to print all non-dominated points, and then print level of dominance of all the points.
This is the code that I have written:
#include <stdio.h>
#include <stdlib.h>
#define MAX 20
#define TRUE 1
#define FALSE 0
typedef struct Coordinates{
float xcord;
float ycord;
}POINT;
//globally declaring dynamic array of points
POINT *Array_of_Points;
//globally declaring dynamic array of non-dominated points
POINT *Non_dominated;
//declaring some functions
int dominance(int n);
int Read_File(char filename[]);
void Xmerge(int head, int middle, int tail);
void XmergeSort(int head, int tail);
void level_of_dominance(int a);
int main(){
char Arr[MAX];
int n, i, d;
printf("Enter file name...");
scanf("%s", Arr);
n = Read_File(Arr);
if(!Read_File(Arr)){ //if error occurs
printf("Terminating program with exit code -1\n");
return -1; //terminate program with return value -1
}
//finds non-dominated points and prints them
d = dominance(n);
printf("The non dominated points are:\n");
for(i = 0; i < d; i++){
printf("(%f, %f)", Non_dominated[i].xcord, Non_dominated[i].ycord);
}
//print all points with levels of dominance
level_of_dominance(n);
printf("End of program... Terminating with exit code 0\n");
free(Array_of_Points);
free(Non_dominated);
return 0;
}
//function reads file in required manner
int Read_File(char filename[]){
int n; //to store number of points present in file
int count = 0;
float x, y;
FILE *fptr = fopen(filename, "r"); //opening given file in readable format
if(!fptr) //file handling if pointer returns null
{
printf("The file %s can't be opened.\n", filename);
return FALSE;
}
fscanf(fptr, "%d", &n); //reading first line consisting of number of points
Array_of_Points = (POINT*)malloc(n * sizeof(POINT)); //allocating memory for npoints
//reading points from file and storing them in globally created dynamic array
while((count < n) && (fscanf(fptr, "%f", &x) == TRUE && fscanf(fptr, "%f", &y) == TRUE)){
Array_of_Points[count].xcord = x;
Array_of_Points[count].ycord = y;
++count;
}
return n; //returns number of points
}
int dominance(int n){ //returns number of non-dominated points
/*METHOD TO FIND DOMINANCE:
* First, arranging points in array by sorting, say, x co-ordinates in DESCENDING ORDER...
* using merge sort algorithm for the same
* The first point in this sorted array is automatically a non dominated point,
* as no other point has x coordinate greater than it
* Then, traverse sorted array and keep track of largest y value, initializing first one to max
* While traversing, the point with y value grater than y max is also non dominated,
* and contributes to new y max and so on...
**/
int foo = 0; //keeps track of number of non-dominated points found so far, initialized to zero
int i = 0;
XmergeSort(0, n);
int ymax = Array_of_Points[0].ycord;
//add first element of the array to Non_dominated array and increase foo count
Non_dominated = (POINT*)malloc(sizeof(POINT));
Non_dominated[0] = Array_of_Points[0];
++foo;
for(; foo < n; foo++){
if(Array_of_Points[foo].ycord > ymax){
++i;
Non_dominated = (POINT*)realloc(Non_dominated, (i + 1) * sizeof(POINT));
Non_dominated[i] = Array_of_Points[foo];
}
}
//all non dominated points stored in array
return i;
}
void level_of_dominance(int a){ //returns number of points dominating a point
int i, j, flag = 0;
for(i = a - 1; i >= 0; i--){
for(j = i; j >= 0; j--){
if((Array_of_Points[i].xcord <= Array_of_Points[j].xcord)&&(Array_of_Points[i].ycord <= Array_of_Points[j].ycord)){
++flag;
}
}
printf("(%f, %f) is dominated by %d points.\n", Array_of_Points[i].xcord, Array_of_Points[i].ycord, flag);
flag = 0; //resetting number of points for next point
}
}
void XmergeSort(int head, int tail){
int mid;
if(head < tail){
mid = (head +tail)/2;
XmergeSort(head, mid);
XmergeSort(mid + 1, tail);
Xmerge(head, mid, tail);
}
}
//function to merge 2 halves of array
void Xmerge(int l, int m, int r)
{
int i, j, k;
int n1 = m - l + 1;
int n2 = r - m;
/* create temp arrays */
POINT *T1, *T2;
T1 = (POINT*)malloc(n1 * sizeof(POINT));
T2 = (POINT*)malloc(n2 * sizeof(POINT));
/* Copy data to temp arrays L[] and R[] */
for (i = 0; i < n1; i++)
T1[i] = Array_of_Points[l + i];
for (j = 0; j < n2; j++)
T2[j] = Array_of_Points[m + 1+ j];
/* Merge the temp arrays back into arr[l..r]*/
i = 0;
j = 0;
k = l;
while (i < n1 && j < n2)
{
Array_of_Points[k] = ((T1[i].xcord <= T2[j].xcord)?T1[i]:T2[j]);
((T1[i].xcord <= T2[j].xcord)?i++:j++);
k++;
}
/* Copy the remaining elements of L[], if there are any */
while (i < n1)
{
Array_of_Points[k] = T1[i];
i++;
k++;
}
/* Copy the remaining elements of R[], if there are any */
while (j < n2)
{
Array_of_Points[k] = T2[j];
j++;
k++;
}
}
While running this code on online gdb, I am getting a segmentation fault, like this:
Reading symbols from a.out...done.
/usr/share/gdb/gdbinit: No such file or directory.
(gdb) run
Starting program: /home/a.out
Enter file name...inp.dat
Testing... no. of non dominated points = 4
The non dominated points are:
Program received signal SIGSEGV, Segmentation fault.
0x0000000000400b82 in level_of_dominance (a=5) at main.c:107
107 if((Array_of_Points[i].xcord <= Array_of_Points[j].xcord)&&(Ar
ray_of_Points[i].ycord <= Array_of_Points[j].ycord)){
(gdb)
The coordinates of non-dominated points aren't being printed here either.
I'm sorry if what I'm asking is stupid, but I hope someone can help me understand what went wrong.
Thanks in advance.
P.S Please let me know if I should edit my question.
EDIT: I had made a bad mistake in line 105 of the code, as pointed out by #JGroven where in place of j--, I had written j++. I have corrected the same above, but my code isn't doing what it should. This is what the debugger is showing:
Reading symbols from a.out...done.
/usr/share/gdb/gdbinit: No such file or directory.
(gdb) run
Starting program: /home/a.out
Enter file name...inp.dat
The non dominated points are:
(0.000000, 0.000000)(2.500000, 7.200000)(4.700000, 5.000000)(5.600000, 9.500000)(9
.000000, 5.900000) is dominated by 0 points.
(5.600000, 9.500000) is dominated by 0 points.
(4.700000, 5.000000) is dominated by 0 points.
(2.500000, 7.200000) is dominated by 0 points.
(0.000000, 0.000000) is dominated by 0 points.
End of program... Terminating with exit code 0
*** Error in `/home/a.out': free(): invalid next size (fast): 0x00000000006034c0 *
**
Program received signal SIGABRT, Aborted.
0x00007ffff7a47c37 in __GI_raise (sig=sig#entry=6)
at ../nptl/sysdeps/unix/sysv/linux/raise.c:56 56 ../nptl/sysdeps/unix/sysv/linux/raise.c: No such file or
directory. (gdb)
EDIT 2: As further pointed out by #Hitokiri,j will become -1 if initialized to i - 1, hence I have changed that to i. And also changed the type of the function to find level of dominance into void.
I figured out my mistake with the help of a friend. The dominance function wasn't completely correct, I have made changes there. And there is something not working properly with the merge sort function I have written, which I shall try to figure out shortly. In the meantime I have replaced it with insertion sort. I am posting my corrected code below.
Thanks to everyone for your help.
#include <stdio.h>
#include <stdlib.h>
#define MAX 20
#define TRUE 1
#define FALSE 0
//segmentation fault...
typedef struct Coordinates{
float xcord;
float ycord;
}POINT;
//globally declaring dynamic array of points
POINT *Array_of_Points;
//globally declaring dynamic array of non-dominated points
POINT *Non_dominated;
//declaring some functions
int dominance(int n);
int Read_File(char filename[]);
/*void Xmerge(int head, int middle, int tail);
void XmergeSort(int);*/
void XInsertion(int n);
int level_of_dominance(int a);
int main(){
char Arr[MAX];
int n, i, d;
printf("Enter file name...");
scanf("%s", Arr);
n = Read_File(Arr);
if(!Read_File(Arr)){ //if error occurs
printf("Terminating program with exit code -1\n");
return -1; //terminate program with return value -1
}
//finds non-dominated points and prints them
d = dominance(n);
printf("The non dominated points are:\n");
for(i = 0; i < d; i++){
printf("(%f, %f)", Non_dominated[i].xcord, Non_dominated[i].ycord);
}
printf("\n");
//print all points with levels of dominance
level_of_dominance(n);
printf("End of program... Terminating with exit code 0\n");
free(Array_of_Points);
free(Non_dominated);
return 0;
}
//function reads file in required manner
int Read_File(char filename[]){
int n; //to store number of points present in file
int count = 0;
float x, y;
FILE *fptr = fopen(filename, "r"); //opening given file in readable format
if(!fptr) //file handling if pointer returns null
{
printf("The file %s can't be opened.\n", filename);
return FALSE;
}
fscanf(fptr, "%d", &n); //reading first line consisting of number of points
Array_of_Points = (POINT*)malloc(n * sizeof(POINT)); //allocating memory to store data of n points
//reading points from file and storing them in globally created dynamic array
while((count < n) && (fscanf(fptr, "%f", &x) == TRUE && fscanf(fptr, "%f", &y) == TRUE)){
Array_of_Points[count].xcord = x;
Array_of_Points[count].ycord = y;
++count;
}
return n; //returns number of points
}
int dominance(int n){ //returns number of non-dominated points
/*METHOD TO FIND DOMINANCE:
* First, arranging points in array by sorting, say, x co-ordinates in DESCENDING ORDER...
* using merge sort algorithm for the same
* The first point in this sorted array is automatically a non dominated point,
* as no other point has x coordinate greater than it
* Then, traverse sorted array and keep track of largest y value, initializing first one to max
* While traversing, the point with y value grater than y max is also non dominated,
* and contributes to new y max and so on...
**/
int foo = 0; //keeps track of number of non-dominated points found so far, initialized to zero
int i;
XInsertion(n);
int ymax = Array_of_Points[0].ycord;
//add first element of the array to Non_dominated array and increase foo count
Non_dominated = (POINT*)malloc(sizeof(POINT));
Non_dominated[0] = Array_of_Points[0];
++foo;
for(i=1 ; i < n; i++){ //note change
if(Array_of_Points[i].ycord > ymax){
ymax=Array_of_Points[i].ycord; /*changes made*/
Non_dominated = (POINT*)realloc(Non_dominated, (foo+1) * sizeof(POINT));
Non_dominated[foo] = Array_of_Points[i];
foo++;
}
}
//all non dominated points stored in array
return foo;
}
int level_of_dominance(int a){ //returns number of points dominating a point
int i, j, flag = 0;
for(i = a - 1; i >= 0; i--){
for(j = i - 1; j >= 0; j--){
if((Array_of_Points[i].xcord <= Array_of_Points[j].xcord)&&(Array_of_Points[i].ycord <= Array_of_Points[j].ycord)){
++flag;
}
}
printf("(%f, %f) is dominated by %d points.\n", Array_of_Points[i].xcord, Array_of_Points[i].ycord, flag);
flag = 0; //resetting number of points for next point
}
}
/*
void XmergeSort(int head, int tail){
int mid;
if(head < tail){
mid = (head +tail)/2;
XmergeSort(head, mid);
XmergeSort(mid + 1, tail);
Xmerge(head, mid, tail);
}
}
//function to merge 2 halves of array
void Xmerge(int l, int m, int r)
{
int i, j, k;
int n1 = m - l + 1;
int n2 = r - m;
// create temp arrays
POINT *T1, *T2;
T1 = (POINT*)malloc(n1 * sizeof(POINT));
T2 = (POINT*)malloc(n2 * sizeof(POINT));
// Copy data to temp arrays L[] and R[]
for (i = 0; i < n1; i++)
T1[i] = Array_of_Points[l + i];
for (j = 0; j < n2; j++)
T2[j] = Array_of_Points[m + 1+ j];
// Merge the temp arrays back into arr[l..r]
i = 0;
j = 0;
k = l;
while (i < n1 && j < n2)
{
Array_of_Points[k] = ((T1[i].xcord <= T2[j].xcord)?T1[i]:T2[j]);
((T1[i].xcord <= T2[j].xcord)?i++:j++);
k++;
}
// Copy the remaining elements of L[], if there are any
while (i < n1)
{
Array_of_Points[k] = T1[i];
i++;
k++;
}
// Copy the remaining elements of R[], if there are any
while (j < n2)
{
Array_of_Points[k] = T2[j];
j++;
k++;
}
}*/
void XInsertion(int n)
{
int i,j;
POINT a;
//Applying insertion-sort on x co-ordinates to have them arranged in decreasing order
for(i=0;i<n;i++)
{
j=i-1;
a=Array_of_Points[i];
while((Array_of_Points[j].xcord<=a.xcord)&&(j>=0))
{
if(Array_of_Points[j].xcord==a.xcord && Array_of_Points[j].ycord>a.ycord)
break;//in case of tie, arrange in decreasing order
else
{
Array_of_Points[j+1]=Array_of_Points[j];
j--;
}
}
Array_of_Points[j+1]=a;
}
}
And here is the output:
Enter file name...inp.dat
The non dominated points are:
(12.600000, 2.300000)(9.000000, 5.900000)(5.600000, 9.500000)
(2.500000, 7.200000) is dominated by 1 points.
(4.700000, 5.000000) is dominated by 2 points.
(5.600000, 9.500000) is dominated by 0 points.
(9.000000, 5.900000) is dominated by 0 points.
(12.600000, 2.300000) is dominated by 0 points.
End of program... Terminating with exit code 0
Any suggestions and tips to improve my program and techniques for debugging are most welcome.
Related
trying to implement a Dijkstra algorithm for my homework.
Faced the "Memory Limit exceedeed" error.
Please tell me what I'm doing wrong.
Memory limit: 8 Mb
Statement You are to write a program that receives a weighted directed graph and finds all distances from fixed vertex S to all
other vertices. Distance from S to some vertex W is the minimal length
of path going from S to W. Length of path is the sum of weights of its
arcs.
Input file contains two integers N, M and S. Vertices are numbered
with integer numbers from 1 to N. S is the number of source vertex. M
is the number of arcs. Each of next M lines contain three integers —
numbers of starting and ending vertices of some arc and its weight
respectively. All weights are positive. There is at most one arc
connecting two vertices in every direction.
Output file must contain N numbers. Each I-th number is the distance
from vertex S to vertex I. If some vertices are not reachable from S,
corresponding numbers must be −1.
Constraints 1 ≤ N, M ≤ 100000 All weights are less or equal 1000.
Sample test:
5 3 1
1 2 5
1 3 7
3 4 10
Out: 0 5 7 17 -1
My programm:
#include <stdio.h>
#include <stdlib.h>
#define INF 100001
typedef enum {max, min} Heap_type;
typedef struct {
Heap_type type;
int *data, size;
} Heap;
Heap init_heap(Heap_type type, int size){
Heap * heap = (Heap*)malloc(sizeof(Heap));
if (heap!=NULL)
{
heap->data = (int *) malloc(size * sizeof(int));
heap->type = type;
heap->size = 0;
}
return *heap;
}
void swap(int *a, int *b){
int tmp = *a;
*a = *b;
*b = tmp;
}
void sift_up(Heap *heap, int id){
heap->size++;
while(heap->type == max ? (heap->data[id] > heap->data[(id - 1) / 2]) : (heap->data[id] < heap->data[(id - 1) / 2])){
swap(&(heap->data[id]), &(heap->data[(id - 1) / 2]));
id = (id - 1) / 2;
}
}
void sift_down(Heap *heap, int id){
int child_l, child_r, child_tmp;
while(2 * id + 1 < heap->size){
child_l = 2 * id + 1;
child_r = 2 * id + 2;
child_tmp = child_l;
if(child_r < heap->size)
if(heap->type == max ? heap->data[child_r] > heap->data[child_l] : heap->data[child_r] < heap->data[child_l])
child_tmp = child_r;
if(heap->type == max ? heap->data[id] >= heap->data[child_tmp] : heap->data[id] <= heap->data[child_tmp])
break;
swap(&(heap->data[id]), &(heap->data[child_tmp]));
id = child_tmp;
}
}
void push(Heap *heap, int num){
heap->data[heap->size] = num;
sift_up(heap, heap->size);
}
int get_root(Heap *heap){
int root = heap->data[0];
heap->size--;
heap->data[0] = heap->data[heap->size];
sift_down(heap, 0);
return root;
}
void fast_dijkstra(int s, int *d, int n, int m, int **W, Heap pq){
for (int i = 0; i<n; i++)
d[i] = INF;
d[s] = 0;
push(&pq, s);
while (pq.size){
int v = get_root(&pq);
for(int u = 0; u<n; ++u) {
if (W[v][u] && (d[v] + W[v][u]) < d[u]) {
d[u] = d[v] + W[v][u];
push(&pq, u);
}
}
}
}
int main() {
FILE *inp = fopen("input.txt", "r"),
*out = fopen("output.txt", "w");
int N, M, S;
fscanf(inp, "%d %d %d", &N, &M, &S);
S -= 1;
int **W = (int **)malloc(N*sizeof(int *));
for(int i = 0; i < N; i++) {
W[i] = (int *)calloc(N, sizeof(int));
}
for (int _=M; _; _--){
int from, to, path;
fscanf(inp,"%d %d %d", &from, &to, &path);
W[from - 1][to - 1] = path;
}
Heap pq = init_heap(min,N);
int d[N];
fast_dijkstra(S, d, N, M, W, pq);
for (int i = 0; i<N; ++i)
fprintf(out, "%d ", d[i] != INF ? d[i] : -1);
return 0;
}
I am learning data structures. I tried to write a function rotate(arr[], d, n) that rotates arr[] of size n by d elements.
By rotate I mean shifting the elements in an array.
The program doesn't give any error, rather it hangs a bit but it doesn't run.
Here's the code: -
#include <stdio.h>
int rotate(int arr[], int d, int n, int dir)
{
int temp, i;
while (d)
{
if (dir)
{
// for left shift
// First element will always get replaced in a rotation.
temp = arr[0];
for (i = 0; i < n - 1; i++)
// for left shifting the second element next to its original position.
arr[i] = arr[i + 1];
// Putting the temp value in the last position.
arr[n - 1] = temp;
}
else
{
// for right shift
// Last element will always get replaced in a rotation.
temp = arr[n - 1];
for (i = n - 1; i > 0; i--)
// for right shifting the second last element to the last position.
arr[i] = arr[i - 1];
// Putting the temp value in the first position
arr[0] = temp;
}
d--;
}
// Print the shifted array
for (i = 0; i < n; i++)
{
printf("%d, ", arr[i]);
}
}
The program only runs when I don't take inputs from the user.
int main()
{
int n;
int arr[n];
int dir;
int d;
printf("Enter the size of the array: \n");
scanf("%d", &n);
printf("Enter the elements of the array: \n");
for (int i = 1; i <= n; i++)
{
printf("Enter element %d", i);
scanf("%d", &arr[i]);
}
printf("Enter the position: \n");
scanf("%d", &d);
printf("Enter the direction: \n");
// 0: Right Direction and 1: Left Direction
scanf("%d", &dir);
// Before shifting the array
for (int i = 1; i <= n; i++)
{
printf("%d, ", arr[i]);
}
// After shifting the array
rotate(arr, d, n, dir);
return 0;
}
You might want to do int arr[n] after scanf("%d", &n); because n is not initialized when you do int arr[n]. Also array indexing in C starts from 0 so for (int i = 1; i <= n; i++) will be for (int i = 0; i < n; i++).
This is not a proper answer, so do not accept it as the correct answer. It is just a possible implementation for educational purposes.
Here is a way to rotate the array so that each element is moved only once (except that the first element of a "group" is moved via a temporary variable).
The rotation amount is specified as an integer with positive values rotating right and negative values rotating left. It converts this amount into a number in the range 0 to n-1 which is the index of the element that will be copied to element 0. It then divides the array into one or more interleaved groups of the same size such that successive elements in each group are separated by the rotation amount in a circular fashion, and rotates the elements within each group. (The number of groups is the greatest common divisor of n and the rotation amount, and the number of elements in each group is the total number of elements divided by the number of groups.)
#include <limits.h>
#include <stddef.h>
static size_t rotate_modulus(int d, size_t n);
static size_t gcd_size(size_t a, size_t b);
/* Rotate arr[] of length n right by d, or left by -d. */
void rotate(int arr[], int d, size_t n)
{
size_t md = rotate_modulus(d, n); /* Get offset in range 0 to n-1. */
if (md)
{
/* Rotation needed. */
/* Divide into interleaved groups and rotate each group. */
size_t num_groups = gcd_size(n, md);
size_t group_size = n / num_groups;
size_t group;
for (group = 0; group < num_groups; group++)
{
size_t a = group; /* Index of first element in group. */
size_t i;
/* Rotate elements in group. */
int temp = arr[a]; /* Get first element. */
for (i = 0; i < group_size - 1; i++)
{
/* Get index of next element in group. */
size_t b = (a + md);
if (a >= n - md)
{
b -= n; /* Index wraps around. */
}
arr[a] = arr[b]; /* Move an element. */
a = b; /* Advance to next index. */
}
arr[a] = temp; /* Move first element to last element. */
}
}
}
/*
* Get modulus for rotation of n elements.
*
* d is the amount to rotate right; negative d rotates left by -d.
*
* For zero n, the return value is 0.
*
* For non-zero n, the return value is n - s, where s is d plus an
* integer multiple of n such that s is in the range 1 to n, and the
* return value is in the range 0 to n - 1.
*/
static size_t rotate_modulus(int d, size_t n)
{
size_t md;
if (n < 2)
{
/* No rotation needed if n < 2. */
md = 0;
}
else if (d >= 0)
{
/* Non-negative d will rotate right. */
md = d % n;
if (md)
{
md = n - md;
}
}
else
{
/* Negative d will rotate left. */
/* -d would overflow if d == INT_MIN && INT_MIN == -INT_MAX - 1. */
int fix_overflow = (d < -INT_MAX);
md = -(d + fix_overflow) % n;
if (fix_overflow)
{
if (++md == n)
{
md = 0;
}
}
}
return md;
}
/*
* If both a and b are non-zero, return the greatest common divisor of a and b.
* Otherwise, return 0.
*/
static size_t gcd_size(size_t a, size_t b)
{
if (b == 0)
{
a = 0;
}
else
{
do
{
size_t t = b;
b = a % b;
a = t;
}
while (b);
}
return a;
}
The code below uses depth-first search over all elements of an adjacency matrix to count how many graphs are represented in the adjacency matrix.
For some reason this code works only for some test cases but not for others, and I'd like to fix this.
#include <stdio.h>
#include <stdlib.h>
//depth-first search
void dfs(int start, int n, int * visited, int ** family){
int current;
visited[start] = 1;
for(current=0;current<n;++current)
if(visited[current] == 0 && family[start][current] == 1) dfs(current, n, visited, family);
}
//set all visited[i] array integers to zero
void zero(int n, int * visited){
int i;
for(i=0;i<n;++i){
visited[i] = 0;
}
}
int main(){
int ** family;
int * visited;
int ** all_visited;
int n, k;
int i, j, x, y;
int counter = 0;
int familycount = 0;
// n == number of elements
// k == number of lines to be read
scanf("%i %i", &n, &k);
//memory allocation
family = (int**) malloc(sizeof(int*) * n);
for(i=0;i<n;++i){
family[i] = (int*) malloc(sizeof(int) * n);
}
all_visited = (int**) malloc(sizeof(int*) * n);
for(i=0;i<n;++i){
all_visited[i] = (int*) malloc(sizeof(int) * n);
}
visited = (int*) malloc(sizeof(int) * n);
zero(n, visited);
//receive input pairs and build adjacency matrix for the graph
for(i=0;i<k;++i){
scanf("%i %i", &x, &y);
--x;
--y;
family[x][y] = 1;
}
//Perform depth-first search for each element in adjacency matrix.
//If dfs() returns a visited[] array that has never been seen before,
// add +1 to familycount.
for(i=0;i<n;++i){
dfs(i,n,visited,family);
for(j=0;j<n;++j){
all_visited[i][j] = visited[j];
}
for(x=0;x<i;++x){
for(y=0;y<n;++y){
if(all_visited[x][y] == 1 && visited[y] == 1) break;
}
if(y == n) ++counter;
}
if(counter == i ) ++familycount;
zero(n, visited);
counter = 0;
}
printf("%i\n",familycount);
return 0;
}
For instance, if we take the following test case:
9 8
1 2
2 3
3 6
4 3
6 5
7 8
1 4
6 2
First line ( "9 8" ) means we have nine possible elements ( integers ranging from 1 to 9 ) and that eight lines of input will follow below.
Possible means that I may or may not input 9 vertexes but never more than 9. If I don't input a vertex, it's ignored.
All following lines mean "X is related to Y", "X belongs to the same family as Y", or more formally, "X and Y belong to the same graph".
As you can see below, this test case has two families or two graphs, so program output should be "2".
This code is a lot more expensive than the problem you're trying to solve.
This problem is knows as graph connectivity in graph theory and you can solve it via a simple DFS for each node; we'll then use the visited array as a storage of the current DFS exploration.
For any vertex v:
visited[v] = 0 <--> v has not been explorated yet
visited[v] < 0 <--> v has an ongoing exploration but it isn't finished yet
visited[v] > 0 <--> v has finished its exploration
Starting from v, we'll mark every reachable vertex from it with the same ongoing value for counter, and once the DFS returns, we'll simply swap sign of the visited[v] value, meaning its exploration is now over.
To get the number of unconnected graphs, you only need to count how many different values are in the visited array.
Here's the code:
#include <stdio.h>
#include <stdlib.h>
void dfs(int start, int n, int *visited, int **family, int counter) {
if (visited[start] > 0)
return;
else if (visited[start] == 0)
visited[start] = -counter;
for (int i = 0; i < n; i++) {
if (family[start][i] == 1 && visited[i]==0) {
dfs(i, n, visited, family, counter);
}
}
visited[start] = -visited[start];
return;
}
//set all visited[i] array integers to zero
void zero(int n, int * visited) {
int i;
for (i = 0; i<n; ++i) {
visited[i] = 0;
}
}
int main() {
int ** family;
int * visited;
int n, k;
int i, x, y;
int counter = 1;
int familycount = 0;
int last = -1;
// n == number of elements
// k == number of lines to be read
printf("Insert vertex# and edge#\n");
scanf("%i %i", &n, &k);
//memory allocation
family = (int**)malloc(sizeof(int*) * n);
for (i = 0; i<n; ++i) {
family[i] = (int*)malloc(sizeof(int) * n);
}
visited = (int*)malloc(sizeof(int) * n);
zero(n, visited);
//receive input pairs and build adjacency matrix for the graph
printf("Now insert all the edges, once at time\nFor edge (a,b), insert a b and press Enter\n");
for (i = 0; i<k; ++i) {
scanf("%i %i", &x, &y);
--x;
--y;
family[x][y] = 1;
}
zero(n, visited);
//Perform depth-first search for each element in adjacency matrix.
//If dfs() returns a visited[] array that has never been seen before,
// add +1 to familycount.
for (i = 0; i<n; ++i) {
dfs(i,n,visited,family,counter);
counter++;
}
for (i = 0; i < n; i++) {
if (visited[i] != last) {
familycount++;
last = visited[i];
}
}
printf("Graph #: %i\n", familycount);
return 0;
}
Instead of giving 9 8 as first input, you'll need to enter 8 8, meaning 8 vertexes and 8 edges, respectively.
What I don't see in your code, nor in the code of a proposed solutuon, is the counting of the unconnected components. I won't give the algoithm in code, just verbally.
Take a random node to start with and apply dfs to mark its nodes. You now have 1 component.
While there are still unmarked nodes, take the node and apply dfs. Add 1 to the number of components.
If there are no unmarked nodes anymore, you have the number of unconnected components of the graph.
I am having issues storing data from a file into my dynamic array. I am aware that what I have now is incorrect but it is just there for the moment. I have a file which on the first line contains the amount of lines of data essentially. The following lines have two integers side by side to represent an ordered pair. I want to store those two integers into a struct, point, that symbolizes an ordered pair. Also, the there is an array with such a struct that is inside of another struct, list , which contains the size of the array, or the amount of data currently stored in the array and a capacity which is the total amount of space in the array.
I want to store the two integers into variables of type int and then store them into a point inside of my array that is in my list struct.
I am getting very confused having two structs and am unsure if this is the correct approach. Any feedback would be welcomed.
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
typedef struct
{
int x;
int y;
} point;
typedef struct
{
int size;
int capacity;
point *A;
} list;
// Compute the polar angle in radians formed
// by the line segment that runs from p0 to p
double polarAngle(point p, point p0)
{
return atan2(p.y - p0.y, p.x - p0.x);
}
// Determine the turn direction around the corner
// formed by the points a, b, and c. Return a
// positive number for a left turn and negative
// for a right turn.
double direction(point a, point b, point c)
{
return (b.x - a.x)*(c.y - a.y) - (c.x - a.x)*(b.y - a.y);
}
int whereSmallest(point A[], int begin, int end, point p0)
{
point min = A[begin];
int where = begin;
int n;
for (n = begin + 1; n < end; n++)
if (polarAngle(A[n], p0) < polarAngle(min, p0))
{
min = A[n];
where = n;
}
return where;
}
void selectionSort(point A[], int N, point p0)
{
int n, s;
point temp;
for (n = 0; n < N; n++)
{
s = whereSmallest(A, n, N, p0);
temp = A[n];
A[n] = A[s];
A[s] = temp;
}
}
// Remove the last item from the list
void popBack(list *p)
{
int x;
x = p->size - 1;
p->A[x] = p->A[x + 1];
}
// Return the last item from the list
point getLast(list *p)
{
point value;
value = p->A[p->size];
return value;
}
// Return the next to the last item
point getNextToLast(list *p)
{
point value;
value = p->A[p->size - 1];
return value;
}
int main(int argc, const char *argv[])
{
point p0, P;
FILE *input;
list *p;
int N, n, x, y;
/*Assuming that the first piece of data in the array indicates the amount of numbers in the array then we record this number as a reference.*/
N = 0;
input = fopen("points.txt", "r");
fscanf(input, "%d", &N);
/*Now that we have an exact size requirement for our array we can use that information to create a dynamic array.*/
p = (point*)malloc(N*sizeof(point));
if (p == NULL)//As a safety precaution we want to terminate the program in case the dynamic array could not be successfully created.
return -1;
/*Now we want to collect all of the data from our file and store it in our array.*/
for (n = 0; n < N; n++)
{
fscanf(input, "%d %d", &P.x, &P.y);
p->A[n] = P.x;
p->A[n] = P.y;
}
fclose(input);
free(p);
return 0;
}
First of all, your code cannot be compiled because this
p->A[n] = P.x;
p->A[n] = P.y;
is wrong, it should be
p->A[n].x = P.x;
p->A[n].y = P.y;
because A has type point and you should access the members of the struct in order to assign values to them.
But this is just the begining of the problems, you didn't allocate space for the A pointer, so this will not work.
You need to allocate space for an instance of type list, which is done this way
p = malloc(sizeof(*p));
Then you need to initialize p's members, for which
p->values = malloc(N * sizeof(point));
p->capacity = N;
p->size = 0;
as you see space was allocated for the values member.
Check fscanf() to insure data integrity and avoid undefined behavior, if fscanf() fails you would never know with your code and you potentially access uninitialized variables which leads to Undefined Behavior.
Capture the values scanned from the file in two int variables and copy them to the array only if the where sucessfuly read
for (n = 0 ; ((n < N) && (fscanf(input, "%d%d", &x, &y) == 2)) ; n++)
/* check that the values were read from the file _______^ */
{
/* store them in the array */
p->values[n].x = x;
p->values[n].y = y;
p->size += 1;
}
Check that the file did open.
I suggest the following code
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
typedef struct
{
int x;
int y;
} point;
typedef struct
{
int size;
int capacity;
point *values;
} list;
// Compute the polar angle in radians formed
// by the line segment that runs from p0 to p
double polarAngle(point p, point p0)
{
return atan2(p.y - p0.y, p.x - p0.x);
}
// Determine the turn direction around the corner
// formed by the points a, b, and c. Return a
// positive number for a left turn and negative
// for a right turn.
double direction(point a, point b, point c)
{
return (b.x - a.x)*(c.y - a.y) - (c.x - a.x)*(b.y - a.y);
}
int whereSmallest(point values[], int begin, int end, point p0)
{
point min = values[begin];
int where = begin;
int n;
for (n = begin + 1; n < end; n++)
if (polarAngle(values[n], p0) < polarAngle(min, p0))
{
min = values[n];
where = n;
}
return where;
}
void selectionSort(point values[], int N, point p0)
{
int n, s;
point temp;
for (n = 0; n < N; n++)
{
s = whereSmallest(values, n, N, p0);
temp = values[n];
values[n] = values[s];
values[s] = temp;
}
}
// Remove the last item from the list
void popBack(list *p)
{
int x;
x = p->size - 1;
p->values[x] = p->values[x + 1];
}
// Return the last item from the list
point getLast(list *p)
{
point value;
value = p->values[p->size];
return value;
}
// Return the next to the last item
point getNextToLast(list *p)
{
point value;
value = p->values[p->size - 1];
return value;
}
int main(int argc, const char *argv[])
{
FILE *input;
list *p;
int N, n, x, y;
/*Assuming that the first piece of data in the array indicates the amount of numbers in the array then we record this number as a reference.*/
N = 0;
input = fopen("points.txt", "r");
if (input == NULL)
return -1;
if (fscanf(input, "%d", &N) != 1)
{
fclose(input);
return -1;
}
p = malloc(sizeof(*p));
if (p == NULL)
return -1;
/*Now that we have an exact size requirement for our array we can use that information to create a dynamic array.*/
p->values = malloc(N * sizeof(point));
p->capacity = N;
p->size = 0;
if (p->values == NULL)//As a safety precaution we want to terminate the program in case the dynamic array could not be successfully created.
{
free(p);
fclose(input);
return -1;
}
/*Now we want to collect all of the data from our file and store it in our array.*/
for (n = 0 ; ((n < N) && (fscanf(input, "%d%d", &x, &y) == 2)) ; n++)
{
p->values[n].x = x;
p->values[n].y = y;
p->size += 1;
}
fclose(input);
free(p->values);
free(p);
return 0;
}
As you can see there is another improvement you can do to the code, it's not too important but it would avoid using the N and n variables which are not necessary.
Note: before using a function, try to read throughly it's documentation, that will prevent all sorts of unexpected results, for example fscanf(), will help you understand my fixes more.
The variable p should be list p.
The points array allocation is p.A = (point*)malloc(N*sizeof(point));
In the filling loop, since A[n] is a point you can't assign it the int P.x or P.y. You can directly put values into the A[n] point like that:
for (n = 0; n < N; n++)
{
fscanf(input, "%d %d", &(p.A[n].x), &(p.A[N].y));
}
The size and capacity of the list should be initialized: p.capacity = N; right after succesfull memory allocation and p.capacity = n; after filling the array
And in the end you should call free(p.A) instead of free(p).
I am working on a class project to solve the wandering Salesman problem, which is basically the TSP, except you don't return to the source. I took the approach of finding all possible permutations of a set of vertices and then iteratively calculating the length and comparing them to find the smallest. I know it's not the best approach, but its what our professor wanted.
When I run the code below, it works fine and gives me the right answers when the input array is less than 7 X 7. But when its 7 X 7, it returns "Bus Error: 10", and if the size is 12 x 12, it returns "Segmentation Fault : 11". I looked up these problems for hours and couldn't figure out what's wrong. I'm not much of an expert in C programming, and I'm honestly really confused with pointers. Thank you so much for the help, I appreciate it greatly!
Oh, and sorry about the messy code.
#include <stdio.h>
#include <math.h>
#include <stdbool.h>
#include <stdio.h>
#include<stdlib.h>
int x = 0;
int a[];
void swap (int v[], int i, int j) {
int t;
t = v[i];
v[i] = v[j];
v[j] = t;
}
/* recursive function to generate permutations */
int* perm (int v[], int n, int i) {
/* this function generates the permutations of the array
* from element i to element n-1
*/
int j;
/* if we are at the end of the array, we have one permutation
* we can use (here we print it; you could as easily hand the
* array off to some other function that uses it for something
*/
if (i == n) {
for (j=0; j<n; j++){ a[x] = v[j]; x++;} // printf ("%d ", v[j]);
// printf ("\n");
}
else
/* recursively explore the permutations starting
* at index i going through index n-1
*/
for (j=i; j<n; j++) {
/* try the array with i and j switched */
swap (v, i, j);
perm (v, n, i+1);
/* swap them back the way they were */
swap (v, i, j);
}
return a;
}
int fact(int n){
if(n==1){
return 1;
}
else{
return n * fact(n-1);
}
}
int findShortestPath(int **v , int length){
int pathArrayMultiplier = 0;
int ShortestPathLength = 99999;
printf("Called");
int arrayOfVertices[length-1];
for(int i=0 ; i<length-1 ; i++){
arrayOfVertices[i] = i+2;
}
int n = fact(length-1);
bool doBreak = false;
int pathArray[length-1];
//printf(" Called 3");
printf(" %d" , n);
int* Answer;
Answer = malloc(sizeof(int *));
Answer = perm(arrayOfVertices , length-1 , 0);
printf("Called 4");
int j =-1;
for(int i=0 ; i< n*(length-1) ; i++){
doBreak = false;
j++;
printf("%d " , *(Answer + i));
pathArray[j] = *(Answer+i);
if(j == length-2)
{
j = -1;
// Check for negative values. If any value is negative, disregard path
int checklength = *((int *)v + 0 *length + (pathArray[0]-1));
if(checklength < 0){
printf("First check called");
continue;}
for(int i =0 ; i<length-2 ; i++){
if(*((int *)v + (pathArray[i]-1) * length + (pathArray[1 + i]-1)) < 0){
doBreak = true;
printf("Second Check called");
break;}
}
if(doBreak) { pathArrayMultiplier++; continue;}
printf("\n");
int pathLength = *((int *)v + 0 *length + (pathArray[0]-1));
for(int i =0 ; i<length-2 ; i++){
pathLength = pathLength + *((int *)v + (pathArray[i]-1) * length + (pathArray[1 + i]-1));}
printf("Path Length is %d\n" , pathLength);
if(pathLength < ShortestPathLength) { ShortestPathLength = pathLength;}
}
}
printf("\n\n Shortest Path Length is %d \n" , ShortestPathLength);
return ShortestPathLength;
}
int main () {
int len = 5;
printf("Array is initialized");
int v[7][7] = {0,7,-1,10,1,-1,-1,7,0,-1,-1,10 ,-1 ,1,-1,-1,0,10,1,10,-1,10,-1,10, 0,8,-1,-1,-1,10,1,8,0,10,-1,-1,-1,10,-1,10,0,70,-1,1,-1,-1,-1, 70 , 0};
printf("Array is initialized");
int **realArrayPointer = v;
findShortestPath(realArrayPointer, 7);
return 0;
}
Your code is a mess and practically unreadable. However, I took it upon myself as a challenge to see if I could spot your bug. What I saw is that you declare an empty array at the top:
int a[];
and then you write to this array:
a[x] = v[j];
x++;
You never even reset x back to 0, anywhere. So basically, right from the start you are writing to unallocated memory, but the bigger your input set, the more unallocated memory you write to.
There could be other problems with your code. I definitely saw a whole bunch of other things that indicated an incorrect understanding of pointers, but they wouldn't necessarily cause a fatal error. Please at the very least get some kind of auto-indent program to make your code readable.