I am trying to order some triangles based on their surface. To do so, the triangles are stored in an array of structs named triangle. To sort this, my idea was to create a sort of parallel array with the surfaces of the triangle and swapping elements of both arrays "in parallel". The sorting is done in a void function that receives the array and the number of elements in it.
The sorting seems to work, I checked by printing the array of surfaces, but when I print the array of triangles (both from inside and outside the function), it is not in the correct order. It is neither the sorted one nor the initial one.
I used bubble sort for sorting, I know it's inefficient but it's also very simple to implement. I know I could have used qsort function, but for learning's sake I'd like to do this from scratch first. Here is the code, hopefully it is readable enough:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
struct triangle {
int a;
int b;
int c;
};
typedef struct triangle triangle;
void sort_by_area(triangle *tr, int n) {
double s[n];
double p, s_2;
int u;
triangle v;
for (int i = 0; i < n; i++) {
p = (tr[i].a + tr[i].b + tr[i].b);
p = p / 2.0;
s_2 = p * (p - tr[i].a) + (p - tr[i].b) + (p - tr[i].c);
s[i] = sqrt(s_2);
}
//bubble sort
for (int i = 0; i < n - 1; i++) {
for (int j = 0; j < (n - i - 1); j++) {
if (s[j] > s[j + 1]) {
u = s[j];
s[j] = s[j + 1];
s[j + 1] = u;
v = tr[j];
tr[j]= tr[j + 1];
tr[j + 1] = v;
//printf("swapped");
}
}
}
for (int i = 0; i < n; i++) {
printf("%f\n", s[i]);
if (i == (n - 1)) {
printf("\n\n");
}
}
}
int main() {
int n;
scanf("%d", &n);
triangle *tr = malloc(n * sizeof(triangle));
for (int i = 0; i < n; i++) {
scanf("%d%d%d", &tr[i].a, &tr[i].b, &tr[i].c);
}
sort_by_area(tr, n);
for (int i = 0; i < n; i++) {
printf("%d %d %d\n", tr[i].a, tr[i].b, tr[i].c);
}
return 0;
}
Here an input example that I tried for testing:
10
67 67 19
3 57 55
33 33 33
61 58 59
23 43 35
48 42 45
23 12 27
41 34 22
26 49 35
63 46 45
My result is
23 12 27
41 34 22
33 33 33
63 46 45
48 42 45
23 43 35
26 49 35
61 58 59
3 57 55
67 67 19
Your calculation for Heron's formula is incorrect, because in
you are first multiplying the semiperimeter,
p, byp - tr[i].a, and then adding it to the result of(p - tr[i].b) + (p - tr[i].c).See: Operator precedence.
Instead, you are looking for the product of the semiperimeter and each side subtracted from the semiperimeter:
Variables for each side simplified.
The first thing to do is simplify your code by writing functions that do one thing, and do it well
and test those functions in isolation
to see if the results are what you expect
and then move on from there.
For sorting, it may be easier to start with the vetted library function
qsort, and a naive approach of recalculating areas at each stepExample usage, with the array defined above.
which when plugged into the previously tested example, gives a good looking result:
After you have a working baseline, start to modify just one part of the program. Here is a modified version of your sort function, using the naive approach of recalculating the areas at each step.
If we test this, it gives the expected results. So we move on to caching the results
which, unsurprisingly, still works because it is built on previously tested code.
Next: benchmark this sort against the naive
qsortapproach.Note: Generally, prefer
size_ttointwhen dealing with object sizes (including array lengths).Note: The VLA
double s[n];will fail for non-positive values ofn, or ifncauses the object to exhaust available (stack) memory.Note:
int u;as the temporary variable for thedoubleswap in your code truncates the left-hand side of the comparison on every swap. This was not a problem when using your data, but would have been if given a data set containing two (or more) floating-point values that convert to the same integer value. A more aggressive warning level from your compiler should highlight this (gcc/clang:-Wconversion[-Wfloat-conversion]).