I have a 2D mesh defined by nodes and elements.
Structure of a node: Node ID, X position, Y position
Structure of an element: Element ID, Node 1, Node 2, Node 3, Node 4
Example of a 2x2 elements mesh:
Nodes:
ID X Y
1 0 0
2 0 1
3 0 2
4 1 0
5 1 1
6 1 2
7 2 0
8 2 1
9 2 2
Elements:
ID N1 N2 N3 N4
1 1 2 4 5
2 2 3 5 6
3 4 5 7 8
4 5 6 8 9
N7-----N8-----N9
| | |
| E3 | E4 |
| | |
N4-----N5-----N6
| | |
| E1 | E2 |
| | |
N1-----N2-----N3
I'm storing both nodes and elements in linked lists.
My question: How can I find the neighbors (nodes) for an arbitrary selected node?
The neighbors of N5, for example, would be N2, N4, N6 and N8.
*Note: This 2x2 element mesh simplified example for explanation proposes, the meshes I'm dealing with may contain several thousands of nodes and elements.
I also have been looking at some concepts of graph theory, but I'm not sure which may be the right way to go.
It would be good to have element's vertices ordered in a way that they make closed polygon. Vertices [1, 2, 4, 5] do not uniquely define first element. From your description it can be seen that you mean that is a polygon with four vertices in order (1, 2, 5, 4). But without picture it can be also degenerated quad (1, 2, 4, 5).
Like:
Elements:
ID N1 N2 N3 N4
1 1 2 5 4
2 2 3 6 5
3 4 5 8 7
4 5 6 9 8
If you are not sure about vertices order, than you have to check about element self-intersection, and reorder vertices to resolve intersections.
With that kind of data it is easy to find all neighbours of given node. Pass through all elements, if element contains given node, than there are two neighbours in that element, vertex before and after in a list.
For node 5, in first element there are neighbours 2 and 4, in second element there are neighbours 6 and 2, ...
If there will be lot of inquires of this kind, than it is better to make extract connectivity information in separate structure. That can be map that maps node to set of it's neighbours. To make it, pass through all elements, and for each element vertex add two neighbours in node's list.
Related
I need to construct a tree given its depth and postorder traversal, and then I need to generate the corresponding preorder traversal. Example:
Depth: 2 1 3 3 3 2 2 1 1 0
Postorder: 5 2 8 9 10 6 7 3 4 1
Preorder(output): 1 2 5 3 6 8 9 10 7 4
I've defined two arrays that contain the postorder sequence and depth. After that, I couldn't come up with an algorithm to solve it.
Here's my code:
int postorder[1000];
int depth[1000];
string postorder_nums;
getline(cin, postorder_nums);
istringstream token1(postorder_nums);
string tokenString1;
int idx1 = 0;
while (token1 >> tokenString1) {
postorder[idx1] = stoi(tokenString1);
idx1++;
}
string depth_nums;
getline(cin, depth_nums);
istringstream token2(depth_nums);
string tokenString2;
int idx2 = 0;
while (token2 >> tokenString2) {
depth[idx2] = stoi(tokenString2);
idx2++;
}
Tree tree(1);
You can do this actually without constructing a tree.
First note that if you reverse the postorder sequence, you get a kind of preorder sequence, but with the children visited in opposite order. So we'll use this fact and iterate over the given arrays from back to front, and we will also store values in the output from back to front. This way at least the order of siblings will come out right.
The first value we get from the input will thus always be the root value. Obviously we cannot store this value at the end of the output array, as it really should come first. But we will put this value on a stack until all other values have been processed. The same will happen for any value that is followed by a "deeper" value (again: we are processing the input in reversed order). But as soon as we find a value that is not deeper, we flush a part of the stack into the output array (also filling it up from back to front).
When all values have been processed, we just need to flush the remaining values from the stack into the output array.
Now, we can optimise our space usage here: as we fill the output array from the back, we have free space at its front to use as the stack space for this algorithm. This has as nice consequence that when we arrive at the end we don't need to flush the stack anymore, because it is already there in the output, with every value where it should be.
Here is the code for this algorithm where I did not include the input collection, which apparently you already have working:
// Input example
int depth[] = {2, 1, 3, 3, 3, 2, 2, 1, 1, 0};
int postorder[] = {5, 2, 8, 9, 10, 6, 7, 3, 4, 1};
// Number of values in the input
int n = sizeof(depth)/sizeof(int);
int preorder[n]; // This will contain the ouput
int j = n; // index where last value was stored in preorder
int stackSize = 0; // how many entries are used as stack in preorder
for (int i = n - 1; i >= 0; i--) {
while (depth[i] < stackSize) {
preorder[--j] = preorder[--stackSize]; // flush it
}
preorder[stackSize++] = postorder[i]; // stack it
}
// Output the result:
for (int i = 0; i < n; i++) {
std::cout << preorder[i] << " ";
}
std::cout << "\n";
This algorithm has an auxiliary space complexity of O(1) -- so not counting the memory needed for the input and the output -- and has a time complexity of O(n).
I won't give you the code, but some hints how to solve the problem.
First, for postorder graph processing you first visit the children, then print (process) the value of the node. So, the tree or subtree parent is the last thing that is processed in its (sub)tree. I replace 10 with 0 for better indentation:
2 1 3 3 3 2 2 1 1 0
--------------------
5 2 8 9 0 6 7 3 4 1
As explained above, node of depth 0, or the root, is the last one. Let's lower all other nodes 1 level down:
2 1 3 3 3 2 2 1 1 0
-------------------
1
5 2 8 9 0 6 7 3 4
Now identify all nodes of depth 1, and lower all that is not of depth 0 or 1:
2 1 3 3 3 2 2 1 1 0
-------------------
1
2 3 4
5 8 9 0 6 7
As you can see, (5,2) is in a subtree, (8,9,10,6,7,3) in another subtree, (4) is a single-node subtree. In other words, all that is to the left of 2 is its subtree, all to the right of 2 and to the left of 3 is in the subtree of 3, all between 3 and 4 is in the subtree of 4 (here: empty).
Now lets deal with depth 3 in a similar way:
2 1 3 3 3 2 2 1 1 0
-------------------
1
2 3 4
5 6 7
8 9 0
2 is the parent for 2;
6 is the parent for 8, 8, 10;
3 is ahe parent for 6,7;
or very explicitly:
2 1 3 3 3 2 2 1 1 0
-------------------
1
/ / /
2 3 4
/ / /
5 6 7
/ / /
8 9 0
This is how you can construct a tree from the data you have.
EDIT
Clearly, this problem can be solved easily by recursion. In each step you find the lowest depth, print the node, and call the same function recursively for each of its subtrees as its argument, where the subtree is defined by looking for current_depth + 1. If the depth is passed as another argument, it can save the necessity of computing the lowest depth.
I have a list of numbers stored in a standard vector. Some of the numbers are children of other numbers. Here is an example
3, 4
3, 5
5, 6
7, 3
8, 9
8, 1
8, 2
9, 8
Or as a graph:
1 2 3-4 5-6 7 8-9
|-------------|
|-----------|
|---|
|-------|
That is there are two clusters 3,4,5,6,7 and 1,2,8,9. The root number is the smallest number of a cluster. Here 3 and 1. I would like to know which algorithms I can use to extract a list like this:
3, 4
3, 5
3, 6
3, 7
1, 2
1, 8
1, 9
An algorithm similar disjoint set union algorithm can help you:
Initialize N disjoint subset, each subset has exactly one number, and root of number i(r(i)) is i.
For each edge (u, v), you can assign:
t = min(r(u), r(v))
r(u) = t
r(v) = t
For each i with i != r(i), you can write out [r(i) - i].
I'm trying to build a search tree on top of my results. Some kind of k-ary tree with n leafs at the end. I'm looking for a C++ solution and experimenting with std::vector but can't get it done as I need memory consistency. It could be done by nested vectors but I can't do that.
Let me explain the details by example:
A unsorted result could be
Result R = { 4, 7, 8, 3, 1, 9, 0, 2, 2, 9, 6 }
On top of that I need a tree with nodes wich in my specific problem are centroids. But to keep it simple I will use artificial values here.
I define the search tree dimensions as
Height H = 2
Branch B = 3
The tree at first
4 7 8 3 1 9 0 2 2 9 6
Second step
layer_0 1.6 5 8.2
| | |
+-+-+-+-+-+ +-+ +-+-+-+
| | | | | | | | | | | |
layer_1 3 1 0 2 2 3 4 6 7 8 9 9
Last step
layer_0 1.6 5 8.2
| | |
+---+---+ +-+---+ +---+----+
layer_1 0.8 1.6 2.4 4.2 5 5.8 6.4 8.2 8.4
| | | | | | |
+-+ +-+-+ | | | | +-+
layer_2 1 0 2 2 3 4 6 7 8 9 9
This last tree is not a k-ary tree as the end-leafs sizes are 0 <= size <= |R|.
At this moment I'm experimenting with two vectors.
std::vector<size_t> layer_2;
std::vector<float> leafs;
std::size_t width, height;
With help of width and height it would be possible to navigate through leafs. But I'm questioning myself how to elegantly connect leafs and layer_2?
How would a good solution look like?
Note: This solution is continuous in the sense that it uses a contiguous data structure (vector or array) instead of a Node pointer style tree, but has the potential to have unused space within the data structure depending on the application.
A case where this approach wastes a lot of space: The max amount of branches per node is large but most nodes actually have far fewer children. This will have no effect on how long it takes to find the leafs though. In fact it is a trade off to make that bit quite fast.
consider a 3 branch tree with 4 levels in continuous memory:
R,a,b,c,aa,ab,ac,ba,bb,bc,ca,cb,cc,aaa,aab,aac,aba,abb,abc,baa.... where the index of a node's children ranges from (parent_index*3)+1 to (parent_index*3)+3
The important caveat I alluded to is that every node must always have it's three child spaces in the vector, array, whatever. If a node has say only 2 children, just fill that extra space with a null_child value to hold the space. (this is where the wasted space comes from)
The advantage is that now, finding all of the leaves is easy.
first_leaf_index = 0
for(i=0;i<(4-1);i++)//in this example 4 is the depth
first_leaf_index += 3^(i) //three is max branches per node
At that point just iterate to the end of the data structure
I wrote a finite element code in fortran 90.
This code is really fast, except the meshing process.
I used triangle and tetgen for meshing in 2D and 3D, respectively, so this process is fast, of course.
For example, for the unit square [0,1]x[0,1] in 2D I have a file with the coordinates of its nodes (for example, a mesh with 5 nodes):
1 0.0 0.0 # coordinates of node 1
2 1.0 0.0 # coordinates of node 2
3 1.0 1.0 # coordinates of node 3
4 0.0 1.0 # coordinates of node 4
5 0.5 0.5 # coordinates of node 5
called coordinate.dat, which have 4 elements (triangles) with nodes called element.dat
1 1 5 4 # vertices of triangle 1
2 1 2 5 # vertices of triangle 2
3 2 3 5 # vertices of triangle 3
4 5 2 4 # vertices of triangle 4
I also have a file where each row i is the number of its initial an final node, called edge.dat:
1 1 2 # initial and final node of edge 1
2 2 3 # initial and final node of edge 2
3 3 4 # initial and final node of edge 3
4 4 1 # initial and final node of edge 4
5 1 5 # initial and final node of edge 5
6 5 2 # initial and final node of edge 6
7 2 5 # initial and final node of edge 7
8 5 4 # initial and final node of edge 8
With this files, I need to generate the following information:
(1) Given an element (triangle or tetrahedron), I need to know the number of its sides (edges and faces, respectively). For example, I need to generate the following structure or file, called struct1.dat:
1 5 8 4 # triangle 1 has the edges number 5, 8 and 4
2 1 6 5 # triangle 2 has the edges number 1, 6 and 5
3 6 2 7 # triangle 2 has the edges number 6, 2 and 7
4 7 3 8 # triangle 4 has the edges number 7, 3 and 8
(2) Furthermore, given a side (edge or face) I need to know the element numbers of the 2 elements (or only one if the side is on the boundary) shared by that side. For example, I need to generate the following structure (or file) called struct2.dat:
1 2 0 # edge number 1 is only on element 2
2 3 0 # edge number 2 is only on element 3
3 4 0 # edge number 3 is only on element 4
4 1 0 # edge number 4 is only on element 1
5 1 2 # edge number 5 is sharing by elements 1 and 2
6 3 2 # edge number 6 is sharing by elements 3 and 2
7 4 3 # edge number 7 is sharing by elements 4 and 3
8 1 4 # edge number 8 is sharing by elements 1 and 4
For both of these structures, struct1.dat and struct2.dat, my code is very slow because I used a brute force approach with a lot of loops..
I am looking for an algorithm (a paper, or better: a subroutine in fortran available for download) optimized for this? I want to continue using triangle and tetgen, but I am willing to listen to other options.
I'm reading Nicolai M. Josuttis's "The C++ standard library, a tutorial and reference", ed2.
He explains the heap data structure and related STL functions in page 607:
The program has the following output:
on entry: 3 4 5 6 7 5 6 7 8 9 1 2 3 4
after make_heap(): 9 8 6 7 7 5 5 3 6 4 1 2 3 4
after pop_heap(): 8 7 6 7 4 5 5 3 6 4 1 2 3
after push_heap(): 17 7 8 7 4 5 6 3 6 4 1 2 3 5
after sort_heap(): 1 2 3 3 4 4 5 5 6 6 7 7 8 17
I'm wondering how could this be figured out? for example, why the leaf "4" under path 9-6-5-4 is the left side child of node "5", not the right side one? And after pop_heap what's the tree structure then? In IDE debugging mode I could only see see the content of the vector, is there a way to figure out the tree structure?
why the leaf "4" under path 9-6-5-4 is the left side child of node "5", not the right side one?
Because if it was on the right side, that would mean there is a gap in the underlying vector. The tree structure is for illustrative purposes only. It is not a representation of how the heap is actually stored. The tree structure is mapped onto the underlying vector via a simple mathematical formula.
The root node of the tree is the first element of the vector (index 0). The index of the left child of a node is obtained from its parent's index by the simple formula: i * 2 + 1. And the index of the right child is obtained by i * 2 + 2.
And after pop_heap what's the tree structure then?
The root node is swapped with the greater of its two children1, and this is repeated until it is at the bottom of the tree. Then it is swapped with the last element. This element is then pushed up the tree, if necessary, by swapping with its parent if it is greater.
The root node is swapped with the last element of the heap. Then, this element is pushed down the heap by swapping with the greater of its two children1. This is repeated until it is in the correct position (i.e. it is not less than either of its children).
So after pop_heap, your tree looks like this:
----- 8 -----
| |
---7--- ---6---
| | | |
-7- -4- -5- x5
| | | | | | x
3 6 4 1 2 3 9
The 9 is not actually part of the heap anymore, but it is still part of the vector until you erase it, via a call pop_back or similar.
1. if the children are equal, as in the case of the adjacent 7's in the tree in your example, it could go either way. I believe that std::pop_heap sends it to the right, though I'm not sure if this is implementation defined
The first element in the vector is the root at index 0. Its left child is at index 1 and its right child at index 2. In general: left_child(i) = 2 * i + 1 and right_child(i) = 2 * i + 2 and parent(i) = floor((i - 1) / 2)
Another way to think about it is the heap fills each level from left to right in the tree. Following the elements in the vector the first level is 9 (1 value), second level 8 6 (2 values) and third level 7 7 5 5 (4 values), and so on. Both these ways will help you draw the heap in a tree structure when given a vector.