Finding all cycles/enclosed shapes in a 2D grid - c#

I have an "infinite" 2D grid and I want to detect closed/complete "structures" - areas of any shape which are enclosed on all sides. However, I need to identify each individual closed circuit - including the larger shape, if any.
In researching this, I've discovered the cycle detection algorithm, but I don't see a clean/efficient way to separate the larger circuit from the smaller ones.
For example given the following two "complete" structures:
0 1 1 1 0
0 1 0 1 0
0 1 1 1 0
0 0 0 0 0
0 1 1 1 1 1
0 1 0 1 0 1
0 1 1 1 1 1
The first is a single cell enclosed by 8 "walls". The cycle detection makes it trivial to detect this.
The second example consists of two copies of example one but they share a wall. There are three separate circuits I care about - the left room, the right room, and the overall structure.
Multiple passes of a cycle algorithm might work, but I'd have to be sure I'm not retracing an already-found shape.
I've also looked at the flood fill algorithm, but it seems like it makes the assumption you already know a point inside the bounded area. With an infinite 2D grid I'd need a size limit to force it to give up if it's not in a valid structure.
Are there solutions I'm missing or have I missed something with my thinking?
I will only do this "check" when a boundary value is added. Using the example above, if I change any 0 -> 1, a new cycle has potentially been created and I'll run the logic. I do not care about identifying separate structures and will always have an origin coordinate.
I've been studying the solutions posted here but they're all based on already knowing which nodes are connected to other nodes. I've already toyed with logic that identifies each individual "line" and I can keep going from there, but it feels redundant.

I would do this like this:
0 0 0 0 0 0 0
0 1 1 1 1 1 0
0 1 0 1 0 1 0
0 1 1 1 1 1 0
0 0 0 0 0 0 0
fill the background with 2
to determine if you are in background just cast a ray and count consequent zeores. Once you find location where the ray length is bigger then circuit size limit you got your start point.
[0]0-0-0-0-0-0
0 1 1 1 1 1 0
0 1 0 1 0 1 0
0 1 1 1 1 1 0
0 0 0 0 0 0 0
2 2 2 2 2 2 2
2 1 1 1 1 1 2
2 1 0 1 0 1 2
2 1 1 1 1 1 2
2 2 2 2 2 2 2
Do not use unbound recursive flood fills for this !!! because for "infinite" area you will stack overflow. You can limit the recursion level and if reached instead of recursion add point to some que for further processing latter. This usually speeds thing up a lot and limits the stack usage...
find first 0
2 2 2 2 2 2 2
2 1 1 1 1 1 2
2 1[0]1 0 1 2
2 1 1 1 1 1 2
2 2 2 2 2 2 2
flood fill it with 3
2 2 2 2 2 2 2
2 1 1 1 1 1 2
2 1 3 1 0 1 2
2 1 1 1 1 1 2
2 2 2 2 2 2 2
select all 1 near 3
this is your circuit. If you remember the bbox while filling #3 then you need to scan only area enlarged by one cell on each side... Selected cells are your circuit.
2 2 2 2 2 2 2
2 * * * 1 1 2
2 * 3 * 0 1 2
2 * * * 1 1 2
2 2 2 2 2 2 2
flood fill 3 with 2
this will avoid of usage already processed circuits
2 2 2 2 2 2 2
2 1 1 1 1 1 2
2 1 2 1 0 1 2
2 1 1 1 1 1 2
2 2 2 2 2 2 2
loop #2 while any 0 found
change all 2 back to 0
0 0 0 0 0 0 0
0 1 1 1 1 1 0
0 1 0 1 0 1 0
0 1 1 1 1 1 0
0 0 0 0 0 0 0

It is a contours finding problem.
One of possible algorithms is described by Satoshi Suzuki and Keiichi Abe in their paper called Topological Structural Analysis of Digitized Binary Images by Border Following in 1985. And it is not trivial. But you can use OpenCV, it's cv2.findContours() function implements this algorithm.
If you choose to use OpenCV, the solution is easy. You extract contours alongside it's hierarchy. Contours that has at least one child (hole) and their child contours are objects that you are looking for. Example using managed OpenCV wrapper called OpenCvSharp:
byte[,] a = new byte[7, 6]
{
{ 0, 1, 1, 1, 0, 0 },
{ 0, 1, 0, 1, 0, 0 },
{ 0, 1, 1, 1, 0, 0 },
{ 0, 0, 0, 0, 0, 0 },
{ 0, 1, 1, 1, 1, 1 },
{ 0, 1, 0, 1, 0, 1 },
{ 0, 1, 1, 1, 1, 1 }
};
// Clone the matrix if you want to keep original array unmodified.
using (var mat = new MatOfByte(a.GetLength(0), a.GetLength(1), a))
{
// Turn 1 pixel values into 255.
Cv2.Threshold(mat, mat, thresh: 0, maxval: 255, type: ThresholdTypes.Binary);
// Note that in OpenCV Point.X is a matrix column index and Point.Y is a row index.
Point[][] contours;
HierarchyIndex[] hierarchy;
Cv2.FindContours(mat, out contours, out hierarchy, RetrievalModes.CComp, ContourApproximationModes.ApproxNone);
for (var i = 0; i < contours.Length; ++i)
{
var hasHole = hierarchy[i].Child > -1;
if (hasHole)
{
var externalContour = contours[i];
// Process external contour.
var holeIndex = hierarchy[i].Child;
do
{
var hole = contours[holeIndex];
// Process hole.
holeIndex = hierarchy[holeIndex].Next;
}
while (holeIndex > -1);
}
}
}

You can try a list of points and verify the ones that are linked.
class PointList : List<Point>
{
/// <summary>
/// Adds the point to the list and checks for perimeters
/// </summary>
/// <param name="point"></param>
/// <returns>Returns true if it created at least one structure</returns>
public bool AddAndVerify(Point point)
{
this.Add(point);
bool result = LookForPerimeter(point, point, point);
Console.WriteLine(result);
return result;
}
private bool LookForPerimeter(Point point, Point last, Point original)
{
foreach (Point linked in this.Where(p =>
(p.X == point.X -1 && p.Y == point.Y)
|| (p.X == point.X + 1 && p.Y == point.Y)
|| (p.X == point.X && p.Y == point.Y - 1)
|| (p.X == point.X && p.Y == point.Y + 1)
))
{
if (!linked.Equals(last))
{
if (linked == original) return true;
bool subResult = LookForPerimeter(linked, point, original);
if (subResult) return true;
}
}
return false;
}
}
This code is intentended as a starting point, it probably has bugs and does not account for perimeters without 0 inside
Example of use:
class Program
{
static void Main(string[] args)
{
PointList list = new PointList();
list.AddAndVerify(new Point() { X = 0, Y = 0 }); //returns false
list.AddAndVerify(new Point() { X = 0, Y = 1 }); //returns false
list.AddAndVerify(new Point() { X = 0, Y = 2 }); //returns false
list.AddAndVerify(new Point() { X = 1, Y = 2 }); //returns false
list.AddAndVerify(new Point() { X = 2, Y = 2 }); //returns false
list.AddAndVerify(new Point() { X = 2, Y = 1 }); //returns false
list.AddAndVerify(new Point() { X = 2, Y = 0 }); //returns false
list.AddAndVerify(new Point() { X = 1, Y = 0 }); //returns True
}
}

Coming from a graph-theoretic view of the problem, you can interpret every 0 of your map as a node, neighboring 0s are connected with an edge. It sounds to me like what you want to do is compute the connected components of this graph (and maybe their connectivity by 1 values, to find 'neighboring rooms' of the same structure)
If you only want to compute this information once, a straightforward approach using a union-find data structure should suffice, where you apply union once per edge.
If you want to edit your map dynamically, the best approach based on the graph model would probably be some dynamic data structure that supports split or de-union operations, see for example here or here

I had a similar problem trying to find all circles inside a 2D street map graph (given as a SVG file). As you state I too could not find an algorithm for that.
I found the following solution though.
Assumptions
Grid Layout:
Each '1' in the grid is in one of the following states (or an homomorphism of that):
1. 0 2. 0 3. 0 4. 0 5. 0 6. 1
0 1 0 1 1 0 1 1 0 1 1 1 1 1 1 1 1 1
0 0 1 0 1 1
But only example 3 to 6 make a sense for a connected wall, as in a connected wall each '1' has at least two '1's in its neighborhood.
Example 3 indicates a corner. This corner holds at most one structure.
Example 4 indicates a straight line. It can be the wall of zero, one or two structures.
Example 5 indicates a t-wall. It can be the wall of zero, one, two or three structures.
Example 6 indicates a cross-wall. It can be the corner of zero, one, two, three or four structures.
The Algorithm
The idea
Assuming the above, the algorithm works by finding a '1' and doing a depth first search, to mark all connected '1's. The traversed '1's are only marked, if the depth first search arrives at the starting position or at an already marked position.
The implementation
I will post an implementation the next few days for that one.

Re-posting my solution with an explanation and some code.
It took a few days before any answers were posted I tried to find a solution and believe I've found one that works very well for my needs.
Since I always have a starting point, I walk the edges from that point and fork the list of visited points each time the path "branches" off - allowing me to find multiple cycles.
Given a 2D grid with either a 1 or 0 in a cell:
0 1 1 1 1 1
0 1 0 1 0 1
0 1 1 1 1 1
Starting from a cell I already know is a 1, I begin my search:
For the current valid point:
add it to a "visited" list
look for any valid neighbors (except for last point I visited, to avoid infinite loops)
For each valid neighbor:
clone the list of points which is our "trail" to this new point
call step 1 with the neighbor point
Cloning allows each "branch" to become a unique cycle without mixing points.
I haven't run any performance profiling, but it works very well given the examples I've thrown at it.
It's possible to give me two copies of a cycle. For example, if I start in the NW corner, cells to the east and south both have valid paths to follow. They're both treated as new paths and followed, but they're just mirror images of the same cycle. For now, I just prune cycles like these - they have exactly the same points, as long as you ignore their order.
There's also a bit of filtering involved - like for problem #1 and trimming points if the end point matches a visited point that wasn't where we started. I think that's pretty much unavoidable and isn't a big deal but if there was a clean way to avoid that I would. I can't know what "begins" a new cycle until I've found it though, so you know, linear time flow strikes again.
public class CycleDetection {
// Cache found cycles
List<Cycle> cycles = new List<Cycle>();
// Provide public readonly access to our cycle list
public ReadOnlyCollection<Cycle> Cycles {
get { return new ReadOnlyCollection<Cycle>(cycles); }
}
// Steps/slopes that determine how we iterate grid points
public Point[] Steps = new Point[] {
new Point(1, 0),
new Point(0, 1),
new Point(-1, 0),
new Point(0, -1)
};
// Cache our starting position
Point origin;
// Cache the validation function
Func<Point, bool> validator;
public CycleDetection(Point origin, Func<Point, bool> validator) {
this.origin = origin;
this.validator = validator;
this.Scan();
}
// Activate a new scan.
public void Scan() {
cycles.Clear();
if (validator(origin)) {
Scan(new List<Point>(), origin);
}
}
// Add a cycle to our final list.
// This ensures the cycle doesn't already exist (compares points, ignoring order).
void AddCycle(Cycle cycle) {
// Cycles have reached some existing point in the trail, but not necessarily
// the exact starting point. To filter out "strands" we find the index of
// the actual starting point and skip points that came before it
var index = cycle.Points.IndexOf(cycle.Points[cycle.Points.Count - 1]);
// Make a new object with only the points forming the exact cycle
// If the end point is the actual starting point, this has no effect.
cycle = new Cycle(cycle.Points.Skip(index).ToList());
// Add unless duplicate
if (!cycles.Contains(cycle)) {
cycles.Add(cycle);
}
}
// Scan a new point and follow any valid new trails.
void Scan(List<Point> trail, Point start) {
// Cycle completed?
if (trail.Contains(start)) {
// Add this position as the end point
trail.Add(start);
// Add the finished cycle
AddCycle(new Cycle(trail));
return;
}
trail.Add(start);
// Look for neighbors
foreach (var step in Steps) {
var neighbor = start + step;
// Make sure the neighbor isn't the last point we were on... that'd be an infinite loop
if (trail.Count >= 2 && neighbor.Equals(trail[trail.Count - 2])) {
continue;
}
// If neighbor is new and matches
if (validator(neighbor)) {
// Continue the trail with the neighbor
Scan(new List<Point>(trail), neighbor);
}
}
}
}
I've posted the full source here: https://github.com/OutpostOmni/OmniGraph (includes some unrelated graph utils as well)

Related

Print all Possible Combinations out a List with Max Values

I’m having an issue with an algorithm I’m trying to implement in C# (the language doesn't matter much I guess).
Let’s say I have a list that could be of any length..for example:
var maxNumbers = new List<int>{5,3,2}();
The numbers in the list represent the maximum value of each entry. For example, the first entry means that it can be any number between 1 and 5 (5 is included).
Now, I want to print all combinations of every possible value for each entry in the list.
To explain:
The first number in the list is 5, so the possible values are 1,2,3,4,5
The second number in the list is 3, so the possible values
are 1,2,3
The last number in the list is 2, so the possible values
are 1,2
My algorithm should print something like:
1-1-1
1-1-2
1-2-1
1-2-2
1-3-1
1-3-2
1-2-1
etc.
I tried to implement this using recursion but wasn't able to get it. Here is my code:
void Iterate(List<int> numbers)
{
if (numbers.Count == 0)
{
Console.WriteLine("");
return;
}
int number = numbers[0];
for (int i = 1; i <= number; i++)
{
Console.WriteLine($"{i} ");
Iterate(numbers.Where((v, index) => index != 0).ToList());
}
}
Can anyone provide insights?
A non recursive approach;
We use Select(Enumerable.Range) to turn your list of maxes into a list of list of ints representing all the numbers..
Then we repeatedly use SelectMany to add another level to the list. SelectMany expects to be fed an enumerable. In the first instance there is only one item in combos, which gets crossed with 5 items from the first entry in ints, so SelectMany produces 5 items.
Second time round SelectMany effectively thinks it's expanding a "5 lists of 3 items" into a "list of 15 items". Third time round SelectMany thinks it's expanding a "15 lists of 2 items" into a "list of 30 items"...
public static string[] Combine(IEnumerable<int> maxes)
{
var ints = maxes.Select(max => Enumerable.Range(1, max));
IEnumerable<string> combos = new[] { "" };
foreach (var i in ints)
{
combos = combos.SelectMany(r => i.Select(x => r + (r == "" ? "" : "-") + x));
}
return combos.ToArray();
}
This answer fixes your code, the crucial problem with which, for me, was that the solution didn't carry any memory of where it had got to so far with making the output, so there isn't any way for iterate to repeat the earlier loop outputs
Here's the fixed code:
static void Iterate(List<int> numbers, string sofar)
{
if (numbers.Count == 0)
{
Console.WriteLine(sofar);
return;
}
for (int i = 1; i <= numbers[0]; i++)
{
Iterate(numbers.Skip(1).ToList(), sofar + i + " ");
}
}
Your code in the question hs a bit of a typo in that it does a WriteLine in the for loop which really messed up the output. Removing that to just Write you get:
1 1 1
2
2 1
2
3 1
2
2 1 1
2
2 1
2
3 1
2
3 1 1
2
2 1
2
3 1
2
4 1 1
2
2 1
2
3 1
2
5 1 1
2
2 1
2
3 1
2
If I add some spaces to change the alignment:
1 1 1
2 --> it's 1 1 2
2 1 --> it's 1 2 1
2 --> it's 1 2 2 etc
3 1
2
2 1 1
2
2 1
2
3 1
2
3 1 1
2
2 1
2
3 1
2
...
You can see it's nearly there, in that it's printing the number that changes each time, it's just lost any memory of what to print in terms of the numbers that haven't changed. The altered code passes the "string we generated so far" and devolves responsibility for printing it to just the if. Each time the loop calls Iterate it passes the string built so far so it keeps that memory of where it got up to

Find similar connected neighbours of a selected cell to form a cluster

I'm new here and this might be a repitition of a previous post but I couldn't find something specific to this. I have a 2d grid containing of random 4 values (0, 1, 2, 3). I want to build an algorithm which finds all the connected neighbours of one particularly selected cell (can be passed by just giving the index of one cell) and highlight them.
For ex:
I have a 2d array:
[0 0 1 0 3 2 0]
[1 3 1 2 1 0 0]
[3 2 3 1 1 1 2]
[0 0 1 2 2 1 0]
[3 2 1 2 1 1 0]
if for example the user selects number 1 (the element highlighted in bold above) i want to find out the cluster that it belongs to and highlight that. Search only for top, bottom, left and right, no diagonals.
Any help would be appreciated.
You are looking for the connected component of a graph, which can be found by depth-first search. Basically you would recursively add all neighbours of the starting node to the output; the details would depend on the specific underlying implementation.
You can Implement the BFS using a queue and a Boolean Array as follows:
void BFS(int srcR, int srcC, int n, int m, int** grid, bool* vis){
int dr[] = {1, -1, 0, 0}; //The change in row
int dc[] = {0, 0, 1, -1}; //The change in column
int target = grid[srcR][srcC];
memset(vis, 0, sizeof vis);
queue<pair<int, int> > q;
q.push({srcR, srcC});
vis[srcR][srcC]=1;
while(!q.empty()){
int ur = q.front().first, uc = q.front().second;
q.pop();
for(int k= 0 ; k < 4 ; ++k){ //The 4 directions we are going to traverse.
int vr = ur + dr[k], vc = uc + dc[k];
if(vr>=0 && vr<n && vc>=0 && vc<m && grid[vr][vc] == target && !vis[vr][vc]){
vis[vr][vc]=1;
q.push({vr, vc});
}
}
}
}
When this function finishes you'll have the vis array with ones denoting the connected component.
I'm sorry if there's any error, as I wrote this from the phone.

Finding next position in 'circular' array

I have an array of 8 compass points numbered from SW, clockwise though to S:
2 3 4
1 5
0 7 6
I want to calculate if the shortest route from one point to another would be clockwise (+1) or anticlockwise (-1). E.g. to go from 7 to 5 would be -1, to go from 7 to 0 would be + 1.
Simple problem I guess but I'm having a real brain freeze today.
The closest I've got is if abs(start - end) < 4, -1, 1 but that doesn't work if the start is 3.
There is a similar problem here, the accepted answer for which is to use modulo, but doesn't explain how. I've thrown various calculations around without success.
Instead of using abs, add 8 (the number of entries) and then take modulo 8, like this:
enum Direction {
None, Clockwise, Counterclockwise
}
public static Direction GetDirection(int a, int b) {
if (a == b) {
return Direction.None;
}
return (a-b+8)%8 > 4 ? Direction.Clockwise : Direction.Counterclockwise;
}
Adding 8 makes the difference non-negative; modulo-8 brings it into 0...7 range.
Note that when the number of steps is 4, it does not matter which way you go, so the program prefers counterclockwise. You can change it by using >= in place of >.
Try this
int start=3;
int end=6;
var temp = start-end;
temp= temp < 0 ? temp + 7 : temp;
var result = temp < 4 ? -1 : 1;

What is the total number of ways in which the bricks can be arranged on the wall?

There is a wall of size 4xN. We have infinite number of bricks of size 4x1 and 1x4. What is the total number of ways in which the bricks can be arranged on the wall so that a new configuration arises every time?
For N = 1, the brick can be laid in 1 format only. For N = 7, one of the ways in which we can lay the bricks is
There are 5 ways of arranging the bricks for N = 7
I solve this problem using dynamic programming:
static int computeBricks(int n)
{
if(n <= 3) { return 1; }
int[] table = new int[n+1];
table[0] = 1;
table[1] = 1;
table[2] = 1;
table[3] = 1;
for(int i = 4; i <= n; ++i)
{
table[i] = table[i-1] + table[i-4];
}
return table[n];
}
But it's just a combination: a guess + intuition. I don't understand this solution completely. Why table[i] = table[i-1] + table[i-4]?
Doesn't it look like the coin change problem?
The number of ways to change amount a using n kinds of coins equals:
the number of ways to change amount a using all but the first kind of coin, plus the number of ways to change amount a - d using all n kinds of coins, where d is the denomination of the first kind of coin.
But I also don't understand how we can use this idea to solve the original problem
Just to be complete, you can do that using simple counting techniques, no algorithm needed.
You have N spots. You have two ways to fill the spots: either one at a time (vertical bricks), or filling 4 consecutive spots in one go (horizontal bricks). You can reformulate that: this is the number of ways you can place K piles of 4 horizontal bricks (K is between 0 and N/4) among N-(3*K) vertical bricks (for each pile of 4 horizontal bricks, you lose 3 spots compared to 1 vertical brick - this is kind of where your [n-4] comes from in your original algorithm).
Let's illustrate that with an example. First of all, the notation choose(n, k) that I use below is the mathematical combination "n choose k", i.e.
Now let's dive in the example. What can you do with N = 15 spots?
You have either K = 0 pile of horizontal bricks (H) and 15 vertical bricks (V): VVVVVVVVVVVVVVV. The number of ways to do that is choose(15, 0) = 1
Or you can place K = 1 H somewhere (you lose three spots by replacing 4 V by 1 H): VVVVHVVVVVVV. The number of ways to do that is choose(15-3, 1) = choose(12, 1) = 12
Or you can place K = 2 H (you lose six spots by replacing 8 V by 2 H): VVHVVVVVH. The number of ways to do that is choose(15-6, 2) = choose(9, 2) = 36
Or you can place K = 3 H (you lose nine spots by replacing 12 V by 3 H): HVVHHV. The number of ways to do that is choose(15-9, 3) = choose(6, 3) = 20
That's it, you have reached the maximum number of horizontal piles (max K = 15/4 = 3). Then you just sum all of these to get the total number of ways you can fill the spots: 1+ 12 + 36 + 20 = 69.
Here is the general formula that directly follows up from this explanation:
Which finally leads to:
There is obviously only one way to arrange the bricks if you have less than 4 columns:
1, 12, 123
1, 12, 123
1, 12, 123
1, 12, 123
However, there are two ways to arrange bricks for the 4-th column.
Way 1 - simply add a column to a correct solution of 3 columns:
1234
1234
1234
1234
Way 2 - remove existing three columns and place four horizontal bricks:
1111
2222
3333
4444
The same logic applies to all consequent columns - you may either take all proper arranges for N-1 and add a column to each of them or take all correct arranges for N-4 and place four bricks horizontally.
The solution is that simple because of one derivation from the problem - you can either place 4 horizontal bricks or 4 vertical bricks, because putting 1 horizontal brick will make placing vertical impossible, and vice versa.
This task would be much more difficult if wall still was 4xN, but bricks were 2x1 and 1x2.
f(n) = f(n-1) + f(n-4) if n >= 4 <p>
f(n) = 1 if 0 <= n < 4

What are "marker for NULL pointers" in binary tree?

I was going through this and this post about binary search tree implementation.
I saw that a binary search tree is represented as (for example):
1 5 7 10 40 50
I was trying to learn about the serialization or de-serialization of the same here. The blog post is making me crazy with those -1s which they're calling markers for NULL pointers. And they're representing the tree as:
20 8 4 -1 -1 12 10 -1 -1 14 -1 -1 -1
Confusion
What are those -1s?
My final goal is to store and read a binary search tree to some kind of file using C# but this confusion is keeping me off.
These -1 stand for places where there is no more childs.
For your example
20
/
8__
/ \
4 12
/\
10 14
You can imagine adding additional -1 (you can use any value that can not occur in the tree itself) to places where nodes have no children:
20
/ \
8__ -1
/ \
4 12
/\ /\
-1 -1 10 14
/\ /\
-1 -1 -1 -1
And now if you go through your tree in "root, then left subtree, then right subtree" order, you will get the following string:
20 8 4 -1 -1 12 10 -1 -1 14 -1 -1 -1
Which is exactly what you have. So this is a way to represent the tree in an array form. At the same time, it is easy to reconstruct the tree from that form. Knowing that these -1s are special in a sense that they have no more children, you can reconstruct the tree from such an array without any ambiguity.
Not all nodes have two children. Obviously, because the tree would be infinite otherwise. At runtime/in memory, a missing node is represented by a nullptr, on disk by -1.
The meaning of these -1's was explained in other answers, let me present the code of reading and writing a tree:
class Tree
{
public:
int value;
Tree* left;
Tree* right;
Tree(int i_value, Tree* i_left, Tree* i_right)
: value(i_value), left(i_left), right(i_right)
{}
Tree(const Tree&) = delete;
static const int NO_TREE = -1;
template<typename Iterator>
static Tree* Create(Iterator& i_iterator)
{
if (*i_iterator == NO_TREE)
{
i_iterator++;
return nullptr;
}
int value = *(i_iterator++);
Tree* left = Create(i_iterator);
Tree* right = Create(i_iterator);
return new Tree(value, left, right);
}
template<typename Iterator>
static void Write(Tree* i_tree, Iterator& i_iterator)
{
if (i_tree == nullptr)
{
*(i_iterator++) = NO_TREE;
return;
}
*(i_iterator++) = i_tree->value;
Write(i_tree->left, i_iterator);
Write(i_tree->right, i_iterator);
}
};
Usage:
vector<int> v = { 20, 8, 4, -1, -1, 12, 10, -1, -1, 14, -1, -1, -1 };
Tree* t = Tree::Create(v.begin());
vector<int> w;
Tree::Write(t, std::back_inserter(w));

Categories