Skip to content

Commit 81cb3be

Browse files
authored
Merge pull request algorithm-archivists#106 from Gathros/CGrahamPR
Adding graham.c
2 parents d9d8405 + 65e069f commit 81cb3be

File tree

2 files changed

+120
-0
lines changed

2 files changed

+120
-0
lines changed
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
#include <math.h>
2+
#include <stddef.h>
3+
#include <stdio.h>
4+
#include <stdlib.h>
5+
#include <string.h>
6+
7+
struct point {
8+
double x, y;
9+
};
10+
11+
int cmp_points(const void *a, const void *b) {
12+
struct point* pa = (struct point*) a;
13+
struct point* pb = (struct point*) b;
14+
15+
if (pa->y > pb->y) {
16+
return 1;
17+
} else if (pa->y < pb->y) {
18+
return -1;
19+
} else {
20+
return 0;
21+
}
22+
}
23+
24+
double ccw(struct point a, struct point b, struct point c) {
25+
return (b.x - a.x) * (c.y - a.y) - (b.y - a.y) * (c.x - a.x);
26+
}
27+
28+
double polar_angle(struct point origin, struct point p) {
29+
return atan2(p.y - origin.y, p.x - origin.x);
30+
}
31+
32+
void polar_angles_sort(struct point *points, struct point origin, size_t size) {
33+
if (size < 2) {
34+
return;
35+
}
36+
37+
double pivot_angle = polar_angle(origin, points[size / 2]);
38+
39+
int i = 0;
40+
int j = size - 1;
41+
while (1) {
42+
while (polar_angle(origin, points[i]) < pivot_angle) {
43+
i++;
44+
}
45+
while (polar_angle(origin, points[j]) > pivot_angle) {
46+
j--;
47+
}
48+
49+
if (i >= j) {
50+
break;
51+
}
52+
53+
struct point tmp = points[i];
54+
points[i] = points[j];
55+
points[j] = tmp;
56+
57+
i++;
58+
j--;
59+
}
60+
61+
polar_angles_sort(points, origin, i);
62+
polar_angles_sort(points + i, origin, size - i);
63+
}
64+
65+
size_t graham_scan(struct point *points, size_t size) {
66+
qsort(points, size, sizeof(struct point), cmp_points);
67+
polar_angles_sort(points, points[0], size);
68+
69+
struct point tmp_points[size + 1];
70+
memcpy(tmp_points + 1, points, size * sizeof(struct point));
71+
tmp_points[0] = tmp_points[size];
72+
73+
size_t m = 1;
74+
for (size_t i = 2; i <= size; ++i) {
75+
while (ccw(tmp_points[m - 1], tmp_points[m], tmp_points[i]) <= 0) {
76+
if (m > 1) {
77+
m--;
78+
continue;
79+
} else if (i == size) {
80+
break;
81+
} else {
82+
i++;
83+
}
84+
}
85+
86+
m++;
87+
struct point tmp = tmp_points[i];
88+
tmp_points[i] = tmp_points[m];
89+
tmp_points[m] = tmp;
90+
}
91+
92+
memcpy(points, tmp_points + 1, size * sizeof(struct point));
93+
94+
return m;
95+
}
96+
97+
int main() {
98+
struct point points[] = {{2.0, 1.9}, {1.0, 1.0}, {2.0, 4.0}, {3.0, 1.0},
99+
{2.0, 0.0}};
100+
101+
printf("Points:\n");
102+
for (size_t i = 0; i < 5; ++i) {
103+
printf("(%f,%f)\n", points[i].x, points[i].y);
104+
}
105+
106+
size_t hull_size = graham_scan(points, 5);
107+
108+
printf("\nHull:\n");
109+
for (size_t i = 0; i < hull_size; ++i) {
110+
printf("(%f,%f)\n", points[i].x, points[i].y);
111+
}
112+
113+
return 0;
114+
}

chapters/computational_geometry/gift_wrapping/graham_scan/graham_scan.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ We can find whether a rotation is counter-clockwise with trigonometric functions
1414
{% method %}
1515
{% sample lang="jl" %}
1616
[import:30-32, lang:"julia"](code/julia/graham.jl)
17+
{% sample lang="c" %}
18+
[import:24-26, lang:"c_cpp"](code/c/graham.c)
1719
{% endmethod %}
1820

1921
If the output of this function is 0, the points are collinear.
@@ -30,6 +32,8 @@ In the end, the code should look something like this:
3032
{% method %}
3133
{% sample lang="jl" %}
3234
[import:34-69, lang:"julia"](code/julia/graham.jl)
35+
{% sample lang="c" %}
36+
[import:65-95, lang:"c_cpp"](code/c/graham.c)
3337
{% endmethod %}
3438

3539
### Bibliography
@@ -41,6 +45,8 @@ In the end, the code should look something like this:
4145
{% method %}
4246
{% sample lang="jl" %}
4347
[import, lang:"julia"](code/julia/graham.jl)
48+
{% sample lang="c" %}
49+
[import, lang:"c_cpp"](code/c/graham.c)
4450
{% endmethod %}
4551

4652
<script>

0 commit comments

Comments
 (0)