Binary Tree nodes and relations to the parent [duplicate] - c

This question already has answers here:
C How to "draw" a Binary Tree to the console [closed]
(10 answers)
Closed 3 years ago.
I know how to code a binary search tree, and to traverse it in inorder, preorder or postorder fashion.
But, I want to know how I can know where the actual node is:
For example let's say we have the values: 70 90 50 60 80 40
So the root would be 70, 90 to its right, 50 to its left, 60 to 50's right and so on.
So if I were to print this inorder, it would be 40 50 60 70 80 90, increasing order pretty much.
I do this by doing this in the recursive traverse function:
traverse(root->left);
printf("%d ", root->data);
traverse(root->right);
But this doesn't let me know (as far as I know) where the node currently is.
Is there a way to print the tree like this?:
70
50 (70 L) 90 (70 R) // We know which parent the node is from and we know if it's the left or the right of it.
40 (50 L) 60 (50 R) 80 (90 L)
and so on.. if the tree is bigger.
I don't really know how I'd do it. Would I need to link them to their parents? But how would I know the right-left thing if I do just that? Or do I need to print the child when the iterator is on the parent still. Thank you in advance.
Edit: I looked up printing the tree by traversing level by level but I don't think I get to know the parent and the side of the node.. I am trying to implement some codes to c code and I always get crashes.

Seems you want to print the tree level by level, i.e.
level 0: node0
level 1: node1 (node0 L) node2 (node0 R)
level 2: ...
So you need a way to track the current level and the target level (i.e. the one you want to print). Also you need a way to track when there is "no more levels" (i.e. no more to print).
That can be done in many ways. The pseudo code below should give you an idea of one way to do it. It's not the most efficient way but it's pretty simple.
Something like:
bool btPrintLevel(node* root, int targetlevel, int currentlevel)
{
if (targetlevel == currentlevel) return false; // no need to go further down in levels
bool result = false;
result |= btPrintLevel(root->left, targetlevel, currentlevel + 1);
// psedo code
if ((currentlevel + 1 == targetlevel)
{
if (childern_exists)
{
printChildern(...)
result = true;
}
}
result |= btPrintLevel(root->right, targetlevel, currentlevel + 1);
return result;
}
Called like:
int level = 0;
while(btPrintLevel(head, level)) ++level;
This How to print elements from Binary Tree by level in c may also help. It doesn't do exactly what you want but with minor modifications you can achieve your goal.

Recursive algorithms are fine for depth-first traversing of trees, but less suitable for broadth-first. The latter can be done pretty efficiently using a FIFO (pseudo code):
push(fifo, { root, 0 });
while(!isEmpty(fifo))
{
node* n = pop(fifo);
print(n);
if(n->left)
push(fifo, { n->left, 'L' });
if(n->right)
push(fifo, { n->right, 'R'});
}
I've foreseen an additional field designating being left or right child of parent. If you your nodes have a link to their parent, you can instead decide upon n->parent->left == n ? 'L' : 'R'.
Leaving implementing the FIFO up to you (you'll find quite a number of questions here on SO about)...

Related

C implementation of an algorithm for flow resolution with non-weighted, bidirectional edges, and nodes with flow capacity

I have tried looking in stack overflow for an answer to my question. I've found those answers, but their solution doesn't really apply to my case, as I have non-directed edges. I cannot create a new vertex with edges going in at Vin and edges goint out at Vout, as there is no "going in" or "out" in a specific direction.
Edmonds-Karp Algorithm for a graph which has nodes with flow capacities
(there was a second stack question that I can't find, but it was the same answer)
Initial problem
My problem is that I have a graph where nodes have a capacity, all edges are bidirectional, and I need to find all the paths that allow me to maximize the flow of N elements through the graph.
Basically it's a lem-in with rooms of capacity 1 and bidirectional edges of infinite capacity.
Imagine a maze where you can have as many people in tunnel, but only one person per room. They can move from one room to another in one turn. How can I make it so that I get all the ways for people to go from the start to the end of the maze, without ever having 2 people in the same room.
Implementation of Edmonds-Karp
I have managed to implement an Edmonds-Karp (probably very poorly), using an adjacency matrix (it's a 1d array of integers using bits to check whether there is connection or not).
I have 3 function, a function that runs the algorithm itself (I'm simplifying the code a bit, such as removing protection for the mallocs, frees, etc... so that the algorithm looks better):
Main algorithm loop
This is the main loop. I try to find an augmenting path. If I don't, that means the end room's (sink) parent will be to the initial value (-1).
Else I apply the path, print the path and continue.
void edmonds_karp(t_map *map)
{
t_deque *deque;
uint32_t *flow;
int64_t *path;
t_way *way;
flow = ft_memalloc(sizeof(uint32_t) * map->size_rooms);
while (TRUE)
{
deque = ft_deque_create();
find_augmenting_path(deque, map, &flow, &path);
if (path[get_end_room(map)->id] == -1)
break ;
apply_augmenting_path(map, &flow, path);
way = build_way_from_path(path, map);
print_way(way);
ft_deque_delete(deque);
}
}
Find the augmenting path
Then there is a function that finds an augmenting path. I just use a BFS with a queue, pop the the parent and then check all the children.
If a children has a forward connection and still has capacity, I add it to the path, mark it visited and push it in the queue.
If a children has a backward connection and flow going through it, I add it to the path, mark it visited and push it in the queue.
static int64_t find_augmenting_path(t_deque *deque, t_map *map, uint32_t **flow, int64_t **path)
{
uint32_t child_id;
uint8_t *visited;
t_room *parent;
t_room *child;
visited = ft_memalloc(sizeof(uint8_t) * map->size_rooms);
ft_deque_push_back(deque, get_start_room(map));
*path = init_path(map->size_rooms);
while (deque->head)
{
parent = ft_deque_pop_front(deque);
child_id = 0;
while (child_id < map->size_rooms)
{
if (!visited[child_id] && !map->rooms[child_id]->visited)
if ((((map->adj_matrix[parent->id] & (1ULL << child_id)) && !((*flow)[parent->id] & (1ULL << child_id))) // There is a forward connection and we still have capacity
|| ((map->adj_matrix[child_id] & (1ULL << parent->id)) && ((*flow)[child_id] & (1ULL << parent->id))))) // There is a backward connection and we have reverse capacity
{
child = get_room_by_id(map, child_id);
visited[child_id] = TRUE;
(*path)[child_id] = parent->id;
ft_deque_push_back(deque, (void*)child);
if (child->type == END)
return (SUCCESS);
}
++child_id;
}
}
return (ERROR);
}
Apply the augmenting path
The function that applies the augmenting path is quite simple, as in my case the capacity is 1 for all edges. We just go back from end (sink), till we reach the start (tap) by using the IDs saved in the path.
For each room, we fill the capacity from parent to child and free capacity from child to parent.
static void apply_augmenting_path(t_map *map, uint32_t **flow, int64_t *path)
{
t_room *start;
t_room *parent;
t_room *child;
start = get_start_room(map);
child = get_end_room(map);
while (child->id != start->id)
{
parent = get_room_by_id(map, path[child->id]);
(*flow)[parent->id] |= 1ULL << child->id;
(*flow)[child->id] |= 0ULL << parent->id;
child = parent;
}
}
There is a check that I have added in following condition:
if (!visited[child_id] && !map->rooms[child_id]->visited)
This check !map->rooms[child_id]->visited) is a visited flag that I add when building my way from the path that I found. It allows me to avoid taking the same room multiple times in some situations.
If I have multiple edges going in, in Edmond-Karps the flow is going to be limited by the edges. It means if I have 4 edge to a node, I can have 2 elements going in, as long as I have 2 other edges for the elements to go out. This checks avoid that situation.
BUT, and that is my main problem, by doing this, I block some possible paths through the maze.
The pictures that follow will show you the problem.
Without my added check, Edmonds-Karp works well, but uses edges to find the best flow:
Here is the solution when I add my check to avoid using the same room twice:
Here is what I would like to find:
Is there any way to modify my Edmonds-Karp implementation to get what I want ?
If not, is there any other algorithm that I could use ?
Thank you all so much for your patience !
PS: I cannot embed pictures as I don't have enough reputation :'(
Let's start with something simple, assuming that we have a simple graph with two nodes A and B, A connected to B: A <-> B
For each node, add one pair of node, SA and EA for A, and SB and EB for B. (S means start and E means end)
From SA, add a directional edge to node EA with capacity equals capacity of node A.
Apply same steps with node B,
Now, we have a graph looks like this:
SA -> EA
SB -> EB
To represent the connection between A and B, we add a directional edge from EA -> SB with unlimited (very large) capacity, similarly, we add a directional edge from EB -> SA
So, our final graph is:
SA -> EA
SB -> EB
EA -> SB
EB -> SA
We realize that, this transformation can be applied easily for more complex graph too, using the similar process.
After applying the transformation, now, we can use standard max flow algorithm to solve this problem. Cheers!

C - How to traverse a Huffman Tree and generate corresponding Huffman codes?

I'm currently working on a program that reads in text from standard input, creates a Huffman tree from the data, and then generates the Huffman codes for the symbols in the Huffman tree.
I'm able to create the Huffman tree, which consists of Tree Node structs that contain the symbol, the frequency of the symbol, the Huffman code for the symbol, and pointers to the let and right nodes. However, I'm kind of stuck on how to traverse the tree and modify each node's "code" according to where it is in the tree.
Essentially what I'm asking is how to traverse a binary tree while modifying a node's elements based on where it is in the tree.
Originally I tried something along the lines of:
void generateCodes (struct HuffTreeNode* root, unsigned long bitShift)
{
struct HuffTreeNode* current = root;
if (root != NULL)
{
current->code |= 0<<bitShift;
generateCodes(root->left,bitShift+1);
current->code |= 1<<bitShift;
generateCodes(root->right,bitShift+1);
}
}
However, that didn't work, and I'm kind of at a loss for what to try next. Any ideas?
You have formed the tree. SO now remains the traversing.
17
/\
/ 7
/ /\
10 / 3
/\ C4 /\
A6 B4 D1 E2
Now initilaly you just put them( the 0's or 1's) in array.Left child link - 1 right child link-0
So in the array you put a[currrent]=1 then call huffmancode(tree->left,current+1)
OR if going to right subtree a[current]=0 then call huffmancode(tree->right,current+1).
At reaching the leaf node print array.
Pseudocode: (printtree)
if (root->left exists)
{
a[current] = 0;
printtree(root->left, a, current + 1);
}
if (root->right exists)
{
a[current] = 1;
printtree(root->right, a,current + 1);
}
if (root is leaf)
{
print a[].
}
I assume that your tree is correctly (and optimally) built.
Each Huffman code is a path from the root to a leaf defining a symbol. You add a 0 when you traverse a left arc and a 1 when you traverse a right arc.
So, a way for getting a list of all the pairs symbol,code consists in traversing recursively the tree. You maintain the current path from the root to the current visited node and when you reach a leaf you generate the pair symbol (which would be stored in the leaf) and the current path.
A data structure for managing the current path is a stack.
So, an algorithm could be as follows:
void codes(struct Node * root, struct Stack * s)
{
if (is_leaf(root))
{
char symbol = // symbol stored in the node
char * code = // the reversed stack content; that is the code of current leaf
printf("symbol %c has code %s\n", symbol, code);
}
s->push('0');
codes(LLINK(root), s);
s->pop();
s->push('1');
codes(RLINK(root), s);
s->pop();
}
I leave to you the details of implementation of the stack and other meta-parts (is_leaf(), LLINK(root), ...).
You can improve the algorithm to generate bits
I hope will be helpful

Removing the last node from Complete Binary Tree

Every node in a Complete Binary Tree can be identified by its label. In other words, a level order traversal of the CBT means accessing nodes in the ascending order of labels. I wrote a function getPointer to return the node given the Root and the Label. For example in the complete binary tree shown below, the key 5 has the label 4, the key 38 has label 3 and so on.
1
/ \
2 38
/
5
Where I am going wrong in the following approach?
I have node structure.
node
{
rightChild
leftChild
value
label
}
C-styled Pseudocode :
getPointer(root, label)
if(label == 1) return root
else
{
temp_node = getPointer(root,label/2);
child = temp_node->left;
if(label == child->label) return child;
else return temp_node->right;
}
I think your code does not handle following scenario:
1
/ \
2 38
\
5
You can simply apply BFS for this problem.
Shouldn't you be checking if your root is a null ptr. There could be a case when the level is not 1, but you are passing a null ptr to your methods. For example, if during recursion, when the right child is null.

animation from 3DS to OpenGL

I am trying to export a 3ds animation to OpenGL and I want to go to the next frame little by little. To do that I use 3ds file with 100 keys so if I do not make mistakes it is ok.
To run my animation I use the lib3ds_file_eval statement but it seems I am doing a mistake
Here is how I do that :
void animationTimer(int value) {
if (g_haltAnimation != 0) {
lib3ds_file_eval(g_scenes3DS[ANIMATED_KART_ID].lib3dsfile, g_currentFrame);
g_currentFrame = (g_currentFrame + 1) % g_scenes3DS[ANIMATED_KART_ID].lib3dsfile->frames;
glutTimerFunc(10, animationTimer, 0);
}
}
So it is quite simple. I put the lib3dsfile of my scene in parameter and the number of the next frame. And when I check the transformation matrix in nodes, it does not change and I can not find why.
I noticed that current_frame in lib3dsFile does not change too, I do not know if it is normal or not.
It is normal behaviour that current_frame in the file does not change. However the matrices of at least some nodes should change for a non-trivial animation.
Did you check the nodes by doing the following?
for (Lib3dsNode* p = g_scenes3DS[ANIMATED_KART_ID].lib3dsfile->nodes; p != 0; p = p->next )
{
// check p->matrix here
}
Make sure to check every matrix because some (most?) nodes probably won't move in a kart animation.

Need help with tree-printing code

I am trying to print this tree:
1
/ \
2 3
/ / \
4 5 6
In this way:
1
2 3
4 5 6
I wrote this code:
void print_g(Tree t)
{
Queue q=initQueue();
Tree tmp=initTree();
if(!isTreeEmpty(t))
enqueue(q,t);
while(!isQueueEmpty(q))
{
tmp=dequeue(q);
printf("%d ",*((int *)Root(tmp)));
if(!isTreeEmpty(subLeft(tmp)))
enqueue(q,subLeft(tmp));
if(!isTreeEmpty(subRight(tmp)))
enqueue(q,subRight(tmp));
}
}
But this code is printed like this:
123456
I can't think of an idea how to solve the print issue.
Can someone write the Pseudo Code??
Thanks.
After you add the children to the queue, create a fake tree node with the value being a newline character and add it to the queue.
You don't have any code to print a newline ('\n') after each generation of the tree.
You need to find some way to tell your program when a tree generation passes and then stick the '\n' in there.
Perhaps:
void print_g(Tree t)
{
Queue q=initQueue();
Tree tmp=initTree();
if(!isTreeEmpty(t))
enqueue(q,t);
int dist = distanceFromTop(t); // new function to tell us which generation we are in
while(!isQueueEmpty(q))
{
tmp=dequeue(q);
if (distanceFromTop(tmp) != dist) // have we changed generation from previous iteration?
printf("\n"); // if so, newline
dist = distanceFromTop(tmp);
printf("%d ",*((int *)Root(tmp)));
if(!isTreeEmpty(subLeft(tmp)))
enqueue(q,subLeft(tmp));
if(!isTreeEmpty(subRight(tmp)))
enqueue(q,subRight(tmp));
}
}
Just be sure that your Tree definition has a member to hold its own distanceFromTop and fill this value in during initTree() to keep the algorithm from getting too slow.

Resources