Skip to content

Commit 0f7ffef

Browse files
committed
Add C++ code for Flood Fill algorithm
1 parent cc457b9 commit 0f7ffef

File tree

3 files changed

+167
-0
lines changed

3 files changed

+167
-0
lines changed

CONTRIBUTORS.md

+1
Original file line numberDiff line numberDiff line change
@@ -59,3 +59,4 @@ This file lists everyone, who contributed to this repo and wanted to show up her
5959
- Mahdi Sarikhani
6060
- Ridham177
6161
- Hugo Salou
62+
- Dimitri Belopopsky
+156
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
#include <array>
2+
#include <cassert>
3+
#include <iostream>
4+
#include <queue>
5+
#include <stack>
6+
#include <vector>
7+
8+
using CartesianIndex = std::array<int, 2>;
9+
10+
auto inbounds(CartesianIndex size, CartesianIndex loc) {
11+
if (loc[0] < 0 || loc[1] < 0) {
12+
return false;
13+
} else if (loc[0] >= size[0] || loc[1] >= size[1]) {
14+
return false;
15+
}
16+
return true;
17+
}
18+
19+
auto find_neighbors(
20+
std::vector<std::vector<float>> const& grid,
21+
CartesianIndex loc,
22+
float old_value,
23+
float /* new_value */) {
24+
25+
std::vector<CartesianIndex> possible_neighbors{
26+
{loc[0], loc[1] + 1},
27+
{loc[0] + 1, loc[1]},
28+
{loc[0], loc[1] - 1},
29+
{loc[0] - 1, loc[1]}};
30+
31+
std::vector<CartesianIndex> neighbors;
32+
33+
for (auto possible_neighbor : possible_neighbors) {
34+
auto size = CartesianIndex{
35+
static_cast<int>(grid[0].size()), static_cast<int>(grid.size())};
36+
auto x = static_cast<std::size_t>(possible_neighbor[0]);
37+
auto y = static_cast<std::size_t>(possible_neighbor[1]);
38+
if (inbounds(size, possible_neighbor) && grid[x][y] == old_value) {
39+
neighbors.push_back(possible_neighbor);
40+
}
41+
}
42+
43+
return neighbors;
44+
}
45+
46+
void recursive_fill(
47+
std::vector<std::vector<float>>& grid,
48+
CartesianIndex loc,
49+
float old_value,
50+
float new_value) {
51+
if (old_value == new_value) {
52+
return;
53+
}
54+
55+
auto x = static_cast<std::size_t>(loc[0]);
56+
auto y = static_cast<std::size_t>(loc[1]);
57+
58+
grid[x][y] = new_value;
59+
60+
auto possible_neighbors = find_neighbors(grid, loc, old_value, new_value);
61+
for (auto possible_neighbor : possible_neighbors) {
62+
recursive_fill(grid, possible_neighbor, old_value, new_value);
63+
}
64+
}
65+
66+
void queue_fill(
67+
std::vector<std::vector<float>>& grid,
68+
CartesianIndex loc,
69+
float old_value,
70+
float new_value) {
71+
if (old_value == new_value) {
72+
return;
73+
}
74+
75+
auto q = std::queue<CartesianIndex>{};
76+
q.push(loc);
77+
auto x = static_cast<std::size_t>(loc[0]);
78+
auto y = static_cast<std::size_t>(loc[1]);
79+
grid[x][y] = new_value;
80+
81+
while (q.size() > 0) {
82+
auto current_loc = q.front();
83+
q.pop();
84+
auto possible_neighbors =
85+
find_neighbors(grid, current_loc, old_value, new_value);
86+
for (auto neighbor : possible_neighbors) {
87+
auto neighbor_x = static_cast<std::size_t>(neighbor[0]);
88+
auto neighbor_y = static_cast<std::size_t>(neighbor[1]);
89+
grid[neighbor_x][neighbor_y] = new_value;
90+
q.push(neighbor);
91+
}
92+
}
93+
}
94+
95+
void stack_fill(
96+
std::vector<std::vector<float>>& grid,
97+
CartesianIndex loc,
98+
float old_value,
99+
float new_value) {
100+
if (old_value == new_value) {
101+
return;
102+
}
103+
104+
auto s = std::stack<CartesianIndex>{};
105+
s.push(loc);
106+
107+
while (s.size() > 0) {
108+
auto current_loc = s.top();
109+
s.pop();
110+
111+
auto x = static_cast<std::size_t>(current_loc[0]);
112+
auto y = static_cast<std::size_t>(current_loc[1]);
113+
114+
if (grid[x][y] == old_value) {
115+
grid[x][y] = new_value;
116+
auto possible_neighbors =
117+
find_neighbors(grid, current_loc, old_value, new_value);
118+
for (auto neighbor : possible_neighbors) {
119+
s.push(neighbor);
120+
}
121+
}
122+
}
123+
}
124+
125+
int main() {
126+
127+
std::vector<std::vector<float>> grid{
128+
{0, 0, 1, 0, 0},
129+
{0, 0, 1, 0, 0},
130+
{0, 0, 1, 0, 0},
131+
{0, 0, 1, 0, 0},
132+
{0, 0, 1, 0, 0}};
133+
134+
std::vector<std::vector<float>> solution_grid{
135+
{1, 1, 1, 0, 0},
136+
{1, 1, 1, 0, 0},
137+
{1, 1, 1, 0, 0},
138+
{1, 1, 1, 0, 0},
139+
{1, 1, 1, 0, 0}};
140+
141+
CartesianIndex start_loc{1, 1};
142+
143+
auto test_grid = grid;
144+
recursive_fill(test_grid, start_loc, 0.0, 1.0);
145+
assert(test_grid == solution_grid);
146+
147+
test_grid = grid;
148+
queue_fill(test_grid, start_loc, 0.0, 1.0);
149+
assert(test_grid == solution_grid);
150+
151+
test_grid = grid;
152+
stack_fill(test_grid, start_loc, 0.0, 1.0);
153+
assert(test_grid == solution_grid);
154+
155+
return EXIT_SUCCESS;
156+
}

contents/flood_fill/flood_fill.md

+10
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,8 @@ In code, this might look like this:
9090
[import:23-41, lang:"julia"](code/julia/flood_fill.jl)
9191
{% sample lang="c" %}
9292
[import:28-46, lang:"c"](code/c/flood_fill.c)
93+
{% sample lang="cpp" %}
94+
[import:18-42, lang:"cpp"](code/cpp/flood_fill.cpp)
9395
{% sample lang="py" %}
9496
[import:10-25, lang="python"](code/python/flood_fill.py)
9597
{% sample lang="coco" %}
@@ -110,6 +112,8 @@ In code, it might look like this:
110112
[import:92-104, lang:"julia"](code/julia/flood_fill.jl)
111113
{% sample lang="c" %}
112114
[import:174-189, lang:"c"](code/c/flood_fill.c)
115+
{% sample lang="cpp" %}
116+
[import:44-59, lang:"cpp"](code/cpp/flood_fill.cpp)
113117
{% sample lang="py" %}
114118
[import:55-63, lang="python"](code/python/flood_fill.py)
115119
{% sample lang="coco" %}
@@ -125,6 +129,8 @@ Additionally, it is possible to do the same type of traversal by managing a stac
125129
[import:43-63, lang:"julia"](code/julia/flood_fill.jl)
126130
{% sample lang="c" %}
127131
[import:79-102, lang:"c"](code/c/flood_fill.c)
132+
{% sample lang="cpp" %}
133+
[import:87-111, lang:"cpp"](code/cpp/flood_fill.cpp)
128134
{% sample lang="py" %}
129135
[import:27-36, lang="python"](code/python/flood_fill.py)
130136
{% sample lang="coco" %}
@@ -168,6 +174,8 @@ The code would look something like this:
168174
[import:66-90, lang:"julia"](code/julia/flood_fill.jl)
169175
{% sample lang="c" %}
170176
[import:149-172, lang:"c"](code/c/flood_fill.c)
177+
{% sample lang="cpp" %}
178+
[import:61-85, lang:"cpp"](code/cpp/flood_fill.cpp)
171179
{% sample lang="py" %}
172180
[import:38-53, lang="python"](code/python/flood_fill.py)
173181
{% sample lang="coco" %}
@@ -250,6 +258,8 @@ After, we will fill in the left-hand side of the array to be all ones by choosin
250258
[import, lang:"julia"](code/julia/flood_fill.jl)
251259
{% sample lang="c" %}
252260
[import, lang:"c"](code/c/flood_fill.c)
261+
{% sample lang="cpp" %}
262+
[import, lang:"cpp"](code/cpp/flood_fill.cpp)
253263
{% sample lang="py" %}
254264
[import:, lang="python"](code/python/flood_fill.py)
255265
{% sample lang="coco" %}

0 commit comments

Comments
 (0)