BST [homework] how does this method of iterative traversal work? - binary-search-tree

I'm using an example from a free book Open Data Structures (in Java) by Pat Morin. I believe i understand the concept of what is going on for tree traversal (keep going left until you can't go any more left, then right and then back up.
I'm a little flummoxed on the code below however. How exactly does it know to change branches in a structure such as:
r(oot)
|
- -
| |
a b
| |
c d
void traverse2() {
Node u = r, prev = nil, next;
while (u != nil) {
if (prev == u.parent) {
if (u.left != nil) next = u.left;
else if (u.right != nil) next = u.right;
else next = u.parent;
} else if (prev == u.left) {
if (u.right != nil) next = u.right;
else next = u.parent;
} else {
next = u.parent;
}
prev = u;
u = next;
} }
from what I can see it automatically goes to parent even though the root has none?

The root's parent is nil, so the algorithm terminates once it leaves the root by its parent (which it does after visiting the right subtree.)

Related

Solidity ++ operator not assigning as expected

Sorry to completely rewrite this post, but I was way off on my troubleshooting. Hopefully this prevents someone's headache in the future...
Now, for example code.
function compare(uint8 a, uint8 b)
private
requireUnpaused
returns(bool)
{
// increment a by 1
a = a++;
// if a + 1 = 3, then loop it around the cycle to be 0
if (a >= 3) {
a = 0;
}
// compare a to b. If a = b, a is the winner - return true
return a == b ? true : false;
}
This code works as expected if I replace "a = a++" with "a = ++a", just "a++" or "++a", or even "a = a + 1".
This drove me crazy for a few days. My question for someone more versed in this than I: Why does "a = a++" not work, when every other way of incrementing "a" by 1 does?

How to print if the value inserted in a BST should be inserted in the left or right subtree

I'm inserting values in a BST and printing "left" if the value should be inserted in the left subtree or "right" if the value should be inserted in the right subtree but when I'm going to print, several right/left are printed, how can I fix it? I think it's due to recursion but I can't solve it without recursion.
BST insertion code:
Node *insert(Node **root, int key)
{
if(*root == NULL)
{
Node *newNode = (Node*)malloc(sizeof(Node));
if(newNode == NULL)
return NULL;
newNode->key= key;
newNode->left = NULL;
newNode->right = NULL;
(*root) = newNode;
return newNode;
}
if(key < (*root)->key){
printf("left ");
return insert(&((*root)->left),key);
}
else{
printf("right ");
return insert((&(*root)->right),key);
}
}
Example:
Inserting the values: 25 - 20 - 36 - 10 - 22 - 30
What I have got from the expected output is that the "left" or "right" indicates the relative position of the node with respect to its parent node.
If this is so, you can do this:
if(key < (*root)->key){
if ( (*root)->left==NULL)
printf("left ");
return insert(&((*root)->left),key);
}
else{
if ( (*root)->right==NULL)
printf("right ");
return insert((&(*root)->right),key);
}
The logic is, We will get to know whether it is left or right just 1 step before the insertion step. I just checked if the next node we are going to , is NULL or not.

CGAL: What is join_facet() really doing with circulators?

I'm trying to use join_facet() iteratively to grow a single facet starting from a given facet_handle. However, I'm running into trouble when using the Halfedge_around_facet_circulator in combination with join_facet(). My while-loop does not become false anymore which works fine if I don't use join_facet() and the circulator seems to point to something else.
I assume that the join operation is somehow changing that Halfedge_around_facet_circulator. But why and how to solve this?
Polyhedron P_out; // is a valid pure triangle Polyhedron
bool merge_next = true;
while (merge_next == true) {
Polyhedron::Halfedge_around_facet_circulator hit = facet_handle->facet_begin(); // facet_handle pointing to facet of P_out
merge_next = false;
do {
if(!(hit->is_border_edge())) {
if (coplanar(hit->facet(), hit->opposite()->facet())) {
if (CGAL::circulator_size(hit->opposite()->vertex_begin()) >= 3 && CGAL::circulator_size(hit->vertex_begin()) >= 3
&& hit->facet()->id() != hit->opposite()->facet()->id()) {
Polyhedron::Halfedge_handle hit2 = hit;
P_out->join_facet(hit2);
merge_next = true;
}
}
}
} while (++hit != facet_handle->facet_begin());
}
What this code should do:
Given the facet_handle, iterate over the corresponding halfedges of facet and merge if possible. Then taking facet_handle of created new facet again and doing the same until no neighboring facets are left to merge.
Edit:
There are areas on which the code runs fine and others where it crashes at hit->is_border_edge() after the first join_facet().

GridWorld Actor - Calling toString() causes a NPE

I am writing a custom Rock in GridWorld. However when, I run the following code:
for(int i = 0;i<7;i++){
Grid<Actor> g = getGrid();
Location l = getLocation();
int x = l.getCol();
int y = l.getRow();
switch(i){
case 0:
Location l1 = new Location(x-1,y-1);
Actor a = g.get(l1);
if((a.toString()).equals("Infectious Rock")){
}else if((a.toString()).equals("Infectious Bug")){
}else{
a.removeSelfFromGrid();
}
break;
(This is repeated 7 more times with different variables and different coordinates)
Here is the NPE:
Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
at infectiousRock.act(infectiousRock.java:18)
Does anyone know what is causing this?
You first have to check if the Actor you get from calling g.get(1l) exists or not. There is a simple fix to this, change your current if statement to:
if(a != null) {
if((a.toString()).equals("Infectious Rock")){
}else if((a.toString()).equals("Infectious Bug")){
}else{
a.removeSelfFromGrid();
}
} else
break;
Adding the extra !=null check should do the trick, and if not leave a comment and I'll do my best to update the answer.

Pathfinding / Deciding on direction

i'm making a simple iPhone game using cocos2d-iphone. I have an array of fiends, the "fiendSet" which has to navigate around a field full of obstacles. I spent the last three nights trying to get my A* pathfinding to work. I found the actual A* implementation here on stackoverflow and it works brilliantly. However, once i try to move my fiends around i run into trouble.
Each of my fiends has a CGPoint called motionTarget which contains the x and y values for where the fiend has to go. If only set the positions x and y to absolute values once a second, it works, like so:
-(void) updateFiendPositions:(ccTime)dt {
for (MSWFiend *currFiend in fiendSet) {
currFiend.position = ccp(currFiend.motionTarget.x,currFiend.motionTarget.y);
}
}
However, this doesn't look very nice, the fiends just "jump" 20px each second instead of animating nicely. I only implemented this as a placeholder method to verify the pathfinding. Now i want smooth animation. This is what i did:
-(void) updatePositions:(ccTime) dt {
for (MSWFiend *currFiend in fiendSet) {
if (currFiend.motionTarget.x != -1 && currFiend.motionTarget.y != -1) {
float x,y;
if ((int)floor(currFiend.position.x) < (int)floor(currFiend.motionTarget.x)) {
x = currFiend.position.x+(currFiend.speed*dt);
}
if ((int)floor(currFiend.position.x) > (int)floor(currFiend.motionTarget.x)) {
x = currFiend.position.x-(currFiend.speed*dt);
}
if (abs((int)floor(currFiend.position.x)-(int)floor(currFiend.motionTarget.x)) < 2) {
x = currFiend.motionTarget.x;
}
if ((int)floor(currFiend.position.y) < (int)floor(currFiend.motionTarget.y)) {
y = currFiend.position.y+(currFiend.speed*dt);
}
if ((int)floor(currFiend.position.y) > (int)floor(currFiend.motionTarget.y)) {
y = currFiend.position.y-(currFiend.speed*dt);
}
if (abs((int)floor(currFiend.position.y)-(int)floor(currFiend.motionTarget.y)) < 2) {
y = currFiend.motionTarget.y;
}
currFiend.position = ccp(x,y);
}
}
}
This works great for fiends moving in one direction. As soon as a fiend is supposed to go around a bend, trouble starts. Instead of for example first going up, then right, then down; my fiends will combine the up/right motion into one, they are "cutting corners". I only want my fiends to move either north/south OR east/west for each position update, not both. In other words, i don't want to animate changes to x and y simultaneously. I hope this explanation is clear enough..
I'm pretty sure i have a logic error somewhere.. i just havn't been able to figure it out for the last three sleepless nights after work.. Help!
You have to keep track of each node in the path to the target. That way you only animate the motion to the next node. Also you can use a CCMoveTo action instead on doing the animation yourself.
#Aleph thanks for your suggestion. I found that it was the code which determines when to assign a new motionTarget, that was faulty, not the code i posted to begin with. When you mentioned keeping track of each nodes position, i thought of my motionTarget determination code and found the error after 2-3 hours. I ended up doing it like this:
-(void) updatePositions:(ccTime) dt {
for (MSWFiend *currFiend in fiendSet) {
int fiendGX,fiendGY,targetGX,targetGY,dGX,dGY;
float x,y,snappedX,snappedY;
BOOL snappedIntoPosition = FALSE;
fiendGX = (int)round(100.0f*(currFiend.position.x/20));
fiendGY = (int)round(100.0f*(currFiend.position.y/20));
targetGX = (int)round(100.0f*(currFiend.motionTarget.x/20));
targetGY = (int)round(100.0f*(currFiend.motionTarget.y/20));
snappedX = currFiend.position.x;
snappedY = currFiend.position.y;
dGX = abs(fiendGX-targetGX);
dGY = abs(fiendGY-targetGY);
float snappingThreshold; //1 = snap when 0.1 from motionTarget.
snappingThreshold = currFiend.speed/10;
if (dGX < snappingThreshold && dGY < snappingThreshold) {
snappingThreshold = currFiend.motionTarget.x;
snappingThreshold = currFiend.motionTarget.y;
int newPathStep;
newPathStep = currFiend.pathStep + 1;
currFiend.pathStep = newPathStep;
}
int gX,gY;
gX = [[currFiend.path objectAtIndex:currFiend.pathStep] nodeX];
gY = (tileMap.mapSize.height-[[currFiend.path objectAtIndex:currFiend.pathStep] nodeY])-1;
currFiend.motionTarget = ccp(gX*20,gY*20); //Assign motion target to the next A* node. This is later used by the position updater.
if (currFiend.motionTarget.x != -1 && currFiend.motionTarget.y != -1) {
x = currFiend.motionTarget.x;
y = currFiend.motionTarget.y;
if ((int)floor(currFiend.position.x) < (int)floor(currFiend.motionTarget.x)) {
//Move right
x = snappedX+(currFiend.speed*dt);
if (x > currFiend.motionTarget.x) {
x = currFiend.motionTarget.x;
}
y = snappedY;
}
if ((int)floor(currFiend.position.x) > (int)floor(currFiend.motionTarget.x)) {
//Move left
x = snappedX-(currFiend.speed*dt);
if (x < currFiend.motionTarget.x) {
x = currFiend.motionTarget.x;
}
y = snappedY;
}
if ((int)floor(currFiend.position.y) < (int)floor(currFiend.motionTarget.y)) {
//Move up
y = snappedY+(currFiend.speed*dt);
if (y > currFiend.motionTarget.y) {
y = currFiend.motionTarget.y;
}
x = snappedX;
}
if ((int)floor(currFiend.position.y) > (int)floor(currFiend.motionTarget.y)) {
//Move down
y = snappedY-(currFiend.speed*dt);
if (y < currFiend.motionTarget.y) {
y = currFiend.motionTarget.y;
}
x = snappedX;
}
}
currFiend.position = ccp(x,y);
}
}