How to rotate a treap or AVL-tree? - c++

Sorry to bother you guys again, but I have a question and i haven't figured it out on my own for several days.
It is about the rotation of a treap, for example, to right rotate a treap at pos.
The question is how to link (or connect) pos->left to pos's original parent?
I found this code online, which works, but i didn't see how it solves my question, is it because of the use of *&? If so, could you help me explain it a little bit?
And what is the function of pos=b is this code?
void Treap::right_rotate(Node *&pos) {
Node *b = pos->left;
pos->left = b->right;
b->right = pos;
pos = b;
}
Thanks in advance!!

The tricky part is indeed the *& part. That declares it as a reference to a pointer (here's a link or two to some similar sample code, but I fear they may be more confusing than helpful).
By changing out the node to which the pointer points with pos = b, you can swap the contents to the different node without having to know the parent. The original reference is updated to be the new rotated node.
Here's a diagram just in case you needed a little overkill of what the rotation looks like (though it sounds like you understand that part).
Initial condition:
Node *&pos;
|
[P]
/ \
L R
/ \ / \
w x y z
You then store the left child since you are about to overwrite it as far as P is concerned.
Node *b = pos->left;
pos->left = b->right;
|
L [P]
/ \ / \
w x R
/ \
y z
Now we finish the rotation since since L is floating in space, breaking proper tree structure:
b->right = pos;
L
/ \ |
w [P]
/ \
x R
/ \
y z
We then finish the upkeep by updating the reference to the node pointer to be the new node that replaces the contents of that place in memory:
pos = b;
|
[L]
/ \
w P
/ \
x R
/ \
y z
Whomever was previously pointing to pos (pos's original parent) now points to the same spot in memory, but that value has now been replaced with the child that has been rotated.

Related

Questions regarding Red-Black Tree Deletion (z has 2 children) (pre-fixDelete)

Code Source - https://github.com/Bibeknam/algorithmtutorprograms/blob/master/data-structures/red-black-trees/RedBlackTree.cpp
y = z;
int y_original_color = y->color;
if (z->left == TNULL) {
x = z->right;
rbTransplant(z, z->right);
} else if (z->right == TNULL) {
x = z->left;
rbTransplant(z, z->left);
} else {
y = minimum(z->right);
y_original_color = y->color;
x = y->right;
if (y->parent == z) {
x->parent = y; \\ [1] Local Class TNull
} else {
rbTransplant(y, y->right); \\ [2] Losing Y
y->right = z->right;
y->right->parent = y;
}
rbTransplant(z, y);
y->left = z->left;
y->left->parent = y;
y->color = z->color; \\ [3] Need of Recoloring
}
Questions
Local Class TNull - (In case y->right is a TNull) Within this class function, TNull is a local pointer simply passed to x; isn't changing the parent of x also change the parent of the local TNull?
Losing Y - This section is meant to be executed in case the minimum in right subtree of z is not a direct children. Later it will be placed at z's location. Won't this segment only pivot y->right / x until it reaches z's location, instead of y / minimum?
Need of Recoloring - Iirc, recoloring will also happen in the later fixDelete() function call, why is this needed?
Please bear with me, I'm slow in this kind of stuff and I'm really at my wits' end. This is the first time I'm asking here. Thank you.
On your questions
Yes that can happen, TNull's parent is set and the authors remark that this is a deliberate design choice which they exploit.
y is moving to where z is and this just fixes y so its pointers are what z had. s
No. Essentially when the node to be deleted has 2 children, you find the successor or predecessor node (which has to have 0 or 1 child) and swap the nodes. You then delete the node at the successor or predecessor node position. The predecessor or successor node swapped, preserves the tree ordering. But the important thing is in swapping the nodes, the colour is not swapped, it must be preserved so the red-black tree properties are still correct.
This is what y_original_color is for.

DWM1000 getting X position

I am currently working on code for use with DWM1000 modules I am using two anchors and one tag I recieve the distance between both anchors to the tag and trying to get the x,y position of the tag. But my x coords for the tag isn't right and seems to be acting like y coord as it changes when i move the tag closer to the anchors I was hoping someone could look at my code and see what I am doing wrong.
float a_r = (pow(-dist_right,2) + pow(dist_left,2) - pow(dist_l_r,2)) / (-2*dist_l_r);
x = dist_l_r/2 - a_r;
float t = pow(dist_right,2) - pow(a_r,2);
if(dist_left < dist_right){
Serial.println("Left");;
}else{
Serial.println("Right");
}
Serial.print("Distance Right: ");Serial.println(dist_right);
Serial.print("Distance Left: ");Serial.println(dist_left);
diff = abs(dist_left - dist_right);
Serial.print("Difference: ");Serial.println(diff);
Serial.print("A_R: ");Serial.println(a_r);
Serial.print("T: ");Serial.println(t);
Serial.print("X: ");Serial.println(x);
Two reference point trilateration yields two solutions - the actual location and a false location. In the case where the reference points form a base line along some impassable barrier such as a wall, then the ambiguity is resolvable by this additional information.
Given:
Attribution: By NavigationGuy - Own work, CC BY-SA 4.0, https://commons.wikimedia.org/w/index.php?curid=75898777
Then
Thus the code:
x = ((dist_left * dist_left) - (dist_right * dist-right) + (dist_l_r * dist_l_r)) /
(2 * dist_l_r) ;
y = sqrt((dist_left * dist_left) - (x * x)) ;
In your code your a_r variable corresponds to x above (my frame of reference is rotated by 90 degrees with respect to yours, but is arbitrary in any case), but your x variable bares no resemblance to y above. Your x variable is proportional to a_r not orthogonal to it, so it is not at all surprising that it varies depending on a_r.
To maintain your frame of reference and variable naming then:
x = sqrt((dist_left * dist_left) - (a_r * a_r)) ;
of if you prefer:
x = sqrt(pow(dist_left,2) - pow(a_r, 2)) ;

Right Runge Kutta 4th method approach?

I have this runge kutta code. However, one mentioned my approach is wrong. And I couldn't really understand why from him, so anyone here, who could give a hint on why this way is wrong?
Vector3d r = P.GetAcceleration();
Vector3d s = P.GetAcceleration() + 0.5*m_dDeltaT*r;
Vector3d t = P.GetAcceleration() + 0.5*m_dDeltaT*s;
Vector3d u = P.GetAcceleration() + m_dDeltaT*t;
P.Velocity += m_dDeltaT * (r + 2.0 * (s + t) + u) / 6.0);
====EDIT====
Vector3d are storing the coordinates, x, y, z.
The GetAcceleration returns the acceleration for each x, y, and z.
You have some acceleration function
a(p,q) where p=(x,y,z) and q=(vx,vy,vz)
Your order 1 system that can be solved via RK4 is
dotp = q
dotq = a(p,q)
The stages of the RK method involve an offset of the state vector(s)
k1p = q
k1q = a(p,q)
p1 = p + 0.5*dt*k1p
q1 = q + 0.5*dt*k1q
k2p = q1
k2q = a(p1,q1)
p2 = p + 0.5*dt*k2p
q2 = p + 0.5*dt*k2q
k3p = q2
k3q = a(p2,q2)
etc. You can either adjust the state vectors of the point P for each step, saving the original coordinates, or use a temporary copy of P to compute k2, k3, k4.
You haven't defined your methods, but the thing that's jumping out at me is you're mixing your results with your inputs. Since Runge-Kutta is a method for calculating y_(n+1) = y_n + hsum(b_ik_i), I would expect your solution to keep your _n terms on the right, and your (n+1) terms on the left. This is NOT what you're doing. Instead, s(n+1) is dependent on r_(n+1) instead of on r_n, t_(n+1) on s_(n+1), and so on. This smells of an error where you attempted to limit the number of variables being used.
With that in mind, can you indicate the actual intermediate values of the calculations your program generates and compare them with the intended intermediate values?

Tree graph: drawing elements which might explode

I'm deciding how to store data and how to draw a tree graph. Assuming I want a minimum space M between two elements, I was thinking I could traverse the entire tree structure from the top to the bottom in breath-first search.
If there's just one element below the current one, it will be drawn with the same X coordinate as his father. If there are two elements, they will be drawn one at -M/2 and the other at +M/2 with respect to their father X coordinate. And so on..
The problem is: what if an element like C (see diagram below) has a great number of children?? I should restructure the entire tree since I should move the element D to the left and make space for all the E-F children of C. Moving D to the left will get the tree crooked and I will need to move B too. Moving B to the left would alter the tree's symmetry so I'll need to move C too and so on..
How can I draw a perfectly symmetric tree whose elements may have a large number of children?
Do it the other way up: compute each node's horizontal position from those of its children after they've been computed. Something like this (WARNING: completely untested code; may consist entirely of bugs):
void Node::place_self(coord_t x0, coord_t y0) {
this->y0 = y0; this->y1 = y0+height;
if (!left && !right) {
// This is a leaf. Put its top left corner at (x0,y0).
this->x0 = x0; this->y0 = y0;
this->subtree_x1 = x0+width;
}
else if (!left || !right) {
// Only one child. Put this immediately above it.
Node * child = left ? left : right;
child->place_self(x0,y0+height+gap);
coord_t xc = child->x0 + child->width/2;
this->x0 = xc-width/2;
this->subtree_x1 = max(this->x0+width, child->subtree_x1);
}
else {
// Two children. Put this above their midline.
left->place_self(x0, y0+height+gap);
right->place_self(left->subtree_x1+gap, y0+height+gap);
coord_t xc = (x0 + right->subtree_x1)/2;
this->x0 = xc-width/2;
this->subtree_x1 = max(this->x0+width, right->subtree_x1);
}
}

Algorithm to simplify a path

Given a path, I want to optimize it so that all verticies that are straight on a line can be removed.
For example:
Path:
*******
* *
* *
***********
Could be optimized to:
*-----*
| \
| \
*---------*
However I want to have control over the deviation from the slope so that it doesnt have to be exactly on the slope.
What sort of algorithm can do this?
Thanks
I believe that you can do this with a simple iterative walk across the points on the path. Keep track, at each point, of the last three points you've encountered. If all three of them are collinear, then remove the middle point from the path, since taking a straight-line path from the first to the third node will pass through the middle node. You could control how much of a deviation there is by having some term that controls how close to collinear the points would have to be.
This can be implemented in O(n) time with a simple pass over the data if you have the points stored in a data structure like a doubly-linked list.
Hope this helps!
You should use the convex hull algorithm (it depends on how is your polygon stocked in memory) and then clean the points with a min angle on both neighbour point. Then you'll have a polygon with only the point at the extremity.
Here it is:
http://en.wikipedia.org/wiki/Convex_hull
They are many possible implementation.It depends on what language you're programing in, and the data you play with..
Edit: I didn't know at time that you had already the points in data.. Just iterate thrue the points and calculate the angle between the one you're on, the prev and the next. if the angle is ~= 180 erase the current point.
This is going to be a bit of an abstracted view since I'm not much of a C++ person, but here goes...
Let's take a look at one point right now:
*******
* *
* *<- this one, lets call it X
***********
What you're going to do is slowly decide if each point is necessary. To decide if a point is valid, other points must be used, the points immediately before and immediately after:
*******
* *<- A
* *
***********<- B
If the angle from A to X is the same (or within an error you deem accurate enough) as the angle from X to B, then X is unnecessary.
This will NOT result in the same outcome as the Convex Hull algorithm. This will simply reduce the resolution of the path. You can get side affects if your allowed error is too great such as this:
* *
* |
* |
* -> |
* |
* |
* *
Or if you're error is too small you may not change the path at all.
Also note that convex hull can greatly change the path, Example:
* * *---*
* * * * / \
* * * -> * *
* * | |
********* *-------*
set `D` to a maximum deviance of 10 degrees or so.
set `P` to the first point.
set `Q` to the point after `P`.
set `A` to the angle from `P` to `Q`.
while `Q` is not that last point in the list
if the angle from `P` to `Q` is within of `A` plus or minus `D`
remove `Q`
else
set `P` to `Q`
set `A` to the angle from `P` to `Q`.
set `Q` to the point after `P`
This is slightly more complicated than the templatetypedef's answer, but has the advantage that it forms a better fit on large curves.
A more complicated solution would involve techniques from image processing. You could try a Hough transform that allows deviations. Deviations can be included by "bluring" the parameter space. However the algorithm is not simple. Also I don't know how well it handles large number of lines, when the number of points on each line is very different. Since your points are ordered you could try to have a look at the parameter space and remove all points that have produced a match. If you select best matches first, you will probably be left with a good solution.
I think this page should help you: Simplyfing Polygons (and I also recommend the book).
I've implemented #templatetypedef's solution in C++, for a closed polygonal chain, described by two x,y vectors. I walk the polygon, and if a point is collinear with the previous and the next point, I delete it:
template<class T> void del_collinear_vanilla(std::vector<T> &x,
std::vector<T> &y) {
assert(x.size() == y.size());
size_t i = x.size();
size_t im1, ip1 = 0;
do {
i--;
im1 = i ? i - 1 : x.size() - 1;
if (are_collinear(x[ip1], y[ip1], x[i], y[i], x[im1], y[im1])) {
x.erase(x.begin() + i);
y.erase(y.begin() + i);
}
ip1 = i;
} while (i != 0);
}
where the implementation depends on a macro/template are_collinear(x0,y0,x1,y1,x2,y2).
However, in some cases I still had some collinear points in the output. This is a sample input with which the algorithm fails:
In the example, P5 coincides with P0 and P4 has the same ordinate of P0 and P1; I changed a little their coordinates to show all the segments. The algorithm should return only a rectangle with vertices P1,P2,P3,P4.
Above, P6 is collinear with P5 and P0. Then, once P6 is eliminated, P5 and P0 coincide, and they are both collinear with P4 and P1.
It turns out that a simple loop over each point, deleting a point if it is collinear with the previous and the next point, does not provide the correct result.
(In the example, let's say you start with P0, and you find that it is not collinear with the point before P6 and the point after P1. Then you move to P1,P2,... until you reach P6. P6 is collinear, you delete it, and the loop is finished. But now P0 is collinear with P4 and P1, and it should have been deleted!)
The same flaw exists for an open path. The algorithm works fine as long as the input path has not collapsed on itself, in a way.
The solution is to take a step back every time you delete a point, to verify if the previous point has now become collinear:
template<class T> void del_collinear(std::vector<T> &x, std::vector<T> &y) {
assert(x.size() == y.size());
size_t target = x.size() - 1;
size_t i = x.size() - 1;
do {
size_t im1 = i ? i - 1 : x.size() - 1;
size_t ip1 = (i == x.size() - 1) ? 0 : i + 1;
if (are_collinear(x[ip1], y[ip1], x[i], y[i], x[im1], y[im1])) {
x.erase(x.begin() + i);
y.erase(y.begin() + i);
// I do not decrease i in this case, as the the previous (alread
// processed) point may now be a collinear point that must be
// deleted. I mod it because i may now exceed x.size()
i = i % x.size();
//Increment the target as well.
target = (i + 1 + x.size()) % x.size();
} else
//go for the next point.
i = i ? i - 1 : x.size() - 1;
} while (i != target);
}