I am asked to implement a recursive function for traversing a general tree (first child, next sibling notation) and a binary tree in depth-first order.
The function should print the node when it last visits it. For example, for the tree below, the nodes should be printed in the following order.
I think I have done the function for the binary tree but I could not do the general one:
Here is my code for the binary tree:
void PostOrder(node* root) {
if (root == NULL)
return;
else {
PostOrder(root->left);
PostOrder(root->right);
printf(‘%c’, root->key);
}
}
Can anyone help?
It sounds like it's a typical "general tree represented as binary tree" with two pointers: first child, and next sibling. We can draw the tree as a standard binary tree, with each child having a down-leading arrow and a right-leading arrow.
I think the tree described in your comment looks like this:
a
|
V
b ------------> c
| |
V V
d --> e --> f g
|
V
h --> i
You want, at each node of the tree, to:
Print all the descendants first, by processing the first child (follow the down arrow).
Then print the node's value
Then process the siblings (follow the right arrow).
Applying this to the tree above, we get:
GeneralTreePostOrder(a) ->
GeneralTreePostOrder(b) -> # Follow child pointer
GeneralTreePostOrder(d) -> # Follow child pointer
# No children
print d
GeneralTreePostOrder(e) -> # Follow sibling pointer
# No children
print e
GeneralTreePostOrder(f) -> # Follow sibling pointer
# No children
print f
# No more siblings
print b
GeneralTreePostOrder(c) -> # Follow sibling pointer
Etc., which prints d e f h i g c a.
Writing a new function for the general tree (N.B. printf should use a double-quoted format string):
void GeneralTreePostOrder (node* root) {
if (root == NULL)
return;
else {
GeneralTreePostOrder (root->left); // Process children
printf ("%c", root->key);
GeneralTreePostOrder (root->right); // Process siblings
}
}
Related
I'm implementing a Red-Black tree for universities purpose and I'm stuck on the property that each path from root to a leaf should have the same number of black nodes.
I've inserted all the functions needed : fixup, rotation, insertion...But I don't know how to handle this function. I was thinking something like :
void checkNuberBlackNodes(struct node* root) {
if( numberBlackNodes(root->right) > numberBlackNodes(root->left) {
leftRotate(root);
colorize(root);
}
else if( numberBlackNodes(root->right) < numberBlackNodes(root->left) {
rightRotate(root);
colorize(root);
}
else return; //no violation, same number of black nodes
}
The idea is to insert a node, fix up the violation and then checkNumberBlackNodes on the new node inserted (or from root).
I don't know how handle this process, all the previous functions were pretty easy to implement this is...I don't know how I could start.
Edit : I had a new idea :
void checkNuberBlackNodes(struct node* root) {
int diff = height(root->right) - height(root->left);
if ( diff >=2 ) //if the tree is too deep
{
leftRotate(root->right);
checkNuberBlackNodes(root->right);
return;
}
else if ( diff <= -2 ) //specular case
{
rightRotate(root->left);
checkNuberBlackNodes(root->left);
return;
}
else if( blackHeight(root->right) > blackHeight(root->left) {
colorize(root->right);
checkNuberBlackNodes(root->right);
return;
}
else if( blackHeight(root->right) < blackHeight(root->left) {
colorize(root->left);
checkNuberBlackNodes(root->left);
return;
}
else return; //No violation
}
blackHeight is the number of black nodes in that path from node to leaf;
If you insert a new node into a Red-Black tree, the node is always a leaf node at the end.
And invariably it is coloured Red.
Generally
(1) Inserting a Node may violate the "no consecutive Red nodes" rule and fixups will be in the direction of the root. A maximum of 2 rotations and 3 * O(h/2) recolourations are required where h is the height of the tree. If the parent of the inserted Node is black, no fixups are required.
(2) Deleting a Node may violate the "count of black nodes from root down every path is the same" rule. Again, fixups occur towards to root. A maximum of 3 rotations and O(h) recolourations are required where h is the height of the tree.
If the Node to be deleted is a the root node with no children, delete it.
If the Node to be deleted has a two children, find the immediate successor (right child then leftwards all the way), swap the Node and successor Node (but PRESERVE the original colours of nodes). The successor Node will always be a 0-children or 1-child node.
Now you need to delete the original Node but in the position of the successor. You move to the next two cases.
If the Node deleted is a leaf node and is red, no fixups are required, delete the node
If the Node to be deleted has a single child, it is black, the child is red, delete the node, replace the Node with the child, recolour the child as black.
So what does this leave?
It leaves a black node that is a leaf node, no children, the difficult case.
Deleting this will violate the "count of black nodes from root down every path is the same" rule.
Having deleted the node, the parent node now has the black path count wrong down one side of the tree. Basically deletion is a two-prong strategy:
a) You examine the parent node, the sibling node, and sibling children's nodes to see if any are red. If they are you can using rotations and recolourations shift this, so the black hole on the deleted side is refilled, repairing tree.
b) and if all the nodes (or NULL nodes) are black, then you make the sibling node red, and the parent node is now considered the point to repair the tree. You have made both sides of tree equally bad and now the fixup point is 1-level higher. You go back to step a) as there is new definition of "parent", "sibling" and "sibling children".
c) It is possible to have a red-black tree which is entirely black. What happens if you reach the root and no red nodes are encountered? Then it now a red-black tree. Effectively , changing siblings has introduced 1 red node in every tree path, reducing the black tree height by 1 uniformly everywhere.
/*
Recursively remove all nodes of the tree
*/
void dispose(node* root)
{
if (root != NULL)
{
dispose(root->left);
dispose(root->right);
free(root);
}
}
I don't understand how this code deletes a whole tree.
What I see is it recursively goes to the left node until it reaches a null node, then goes to the right node, then keeps going to the left again till null, then to the right and if null then free the parent.
It seems it deletes the last leaf of a tree instead of the whole thing,
Could someone explain the process of code as I tried to above if I'm mistaken?
It can help a lot to write out the sequence of function calls that will be made as your program executes. Here's an example tree:
A
B C
D E F G
For this tree, the sequence of function calls will be:
dispose(A)
dispose(B)
dispose(D)
dispose(NULL)
dispose(NULL)
free(D)
dispose(E)
dispose(NULL)
dispose(NULL)
free(E)
free(B)
dispose(C)
dispose(F)
dispose(NULL)
dispose(NULL)
free(F)
dispose(G)
dispose(NULL)
dispose(NULL)
free(G)
free(C)
free(A)
Now, I understand that code below works only for root and its children, but I don't know how to expand it. Every node must have children before passing on "grandchildren". Thank you.
void insert_node(IndexTree **root, Node *node) {
IndexTree *temp = (IndexTree*)malloc(sizeof(IndexTree));
memcpy(&temp->value.cs, node, sizeof(Node));
temp->left = NULL;
temp->right = NULL;
temp->tip=1;
if ((*root) == NULL) {
*root = temp;
(*root)->left = NULL;
(*root)->right = NULL;
}
else {
while (1) {
if ((*root)->right == NULL) {
(*root)->right = temp;
break;
}
else if ((*root)->left == NULL) {
(*root)->left = temp;
break;
}
}
}
Use recursive functions.
Trees are recursive data types (https://en.wikipedia.org/wiki/Recursive_data_type). In them, every node is the root of its own tree. Trying to work with them using nested ifs and whiles is simply going to limit you on the depth of the tree.
Consider the following function: void print_tree(IndexTree* root).
An implementation that goes over all values of the trees does the following:
void print_tree(IndexTree* root)
{
if (root == NULL) return; // do NOT try to display a non-existent tree
print_tree(root->right);
printf("%d\n", root->tip);
print_tree(root->left);
}
The function calls itself, which is a perfectly legal move, in order to ensure that you can parse an (almost) arbitrarily deep tree. Beware, however, of infinite recursion! If your tree has cycles (and is therefore not a tree), or if you forget to include an exit condition, you will get an error called... a Stack Overflow! Your program will effectively try to add infinite function calls on the stack, which your OS will almost certainly dislike.
As for inserting, the solution itself is similar to that of printing the tree:
void insert_value(IndexTree* root, int v)
{
if (v > root->tip) {
if (root->right != NULL) {
insert_value(root->right, v);
} else {
// create node at root->right
}
} else {
// same as above except with root->left
}
}
It may be an interesting programming question to create a Complete Binary Tree using linked representation. Here Linked mean a non-array representation where left and right pointers(or references) are used to refer left and right children respectively. How to write an insert function that always adds a new node in the last level and at the leftmost available position?
To create a linked complete binary tree, we need to keep track of the nodes in a level order fashion such that the next node to be inserted lies in the leftmost position. A queue data structure can be used to keep track of the inserted nodes.
Following are steps to insert a new node in Complete Binary Tree. (Right sckewed)
1. If the tree is empty, initialize the root with new node.
2. Else, get the front node of the queue.
……. if the right child of this front node doesn’t exist, set the right child as the new node. //as per your case
…….else If the left child of this front node doesn’t exist, set the left child as the new node.
3. If the front node has both the left child and right child, Dequeue() it.
4. Enqueue() the new node.
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
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.