Binary Tree Transfer - c

How to transfer a binary tree (not a balanced tree) across two different systems efficiently, retaining its complete structure?

The obvious way would be to convert your binary tree to an array of nodes, replacing each pointer in the original tree with an index to a node in the array. You can then transmit that array, and on the other end reconstruct a tree with identical structure.

This structure given below
[x]
/ \
[L] [R]
\
[P]
can be translated easily into
(X,(L,-,(P,-,-)),(R,-,-))
Also, read a post by Eric Lippert.
NOTE: I feel, similar thing should work for arbitrary trees. Any comments?

Define serialization functions.
void serialize( FILE *f, my_tree *node, _Bool is_root ) {
if ( node == NULL ) {
fputc( no_child, f );
return;
}
if ( ! is_root ) fputc( data_prefix, f );
write_data( f, node->data );
fputc( data_terminator, f );
write_data( node->left_child );
write_data( node->right_child );
}
void deserialize_node( FILE *f, my_tree *node ) {
node->data = read_data_field( f );
if ( fgetc( f ) != no_child ) {
node->left_child = calloc( 1, sizeof( my_tree ) );
deserialize( f, node->left_child, false );
}
if ( fgetc( f ) != no_child ) {
node->right_child = calloc( 1, sizeof( my_tree ) );
deserialize( f, node->right_child, false );
}
}
Come to think of it, this simple scheme (where data_terminator and no_child must be single characters) allows both data_terminator and no_child to be equal.

The main issue with this is that you have to replace pointers or references from your in memory representation with something else that can be used to unambiguously represent the node that was pointed to.
foo
/ \
cat zebra
\
dog
One way to do this is to exchange the pointers for keys -- more like an array index than a proper pointer.
1 2 "foo"
3 _ "cat"
_ _ "zebra"
_ _ "dog"
In this representation the first field is the line number (counting starts at 0, which is the root node) of the left child, the second field is the right child, and the third field is the value. The tree is ordered alphabetically. This seems simple, but can be difficult to actually do.
A similar approach would put the key in each entry rather than rely on position. This method could use the original pointers as the keys and the read-in code would have to build a translation/symbol table to switch between the keys and new pointers.
Another way to go about this is with a lisp-esque tree:
(foo (cat () (dog () ()) (zebra () () ))
Formatted for easy viewing:
(foo
(cat
()
(dog
()
()
)
)
(zebra
()
()
)
)
This can be easily generated by a simple in order traversal. It can also be read in with a very simple recursive decent parser. You can also alter this to decrease the sizes of leaf nodes in the serialized format by omitting the nil or () or whatever you chose for NULL pointers.
Another method, which is similar to the first, is to store all of tree in one chunk of memory that can be dumped to and read back from disk. The pointers in this would be relative to the beginning of this memory chunk, rather than absolute pointers. This would be a fast way for two programs on the same type of machine (using the same CPU memory width) to share trees (or other graphs), but is likely to be difficult to implement.
The lisp-esqe version of this is super easy to implement, but does not easily extend to things that aren't trees, where there could be a cyclic reference or more than one parent for a particular node, though it can be done. It also does not easily extend to handle storing more than one structure in a particular file.
The line positional index version works for most types of graphs, but storing more than one structure in a particular file would need to alter this format somewhat.
No matter what you choose you will need to make sure you can handle all values that could be present as node data. For instance if the node data could contain a ", ), or \n then it might cause problems in some of the formats I've show, and those characters would need to be escaped. You could prefix fields with their length or use constant structure layout to account for this, though.
You will also need to make sure that any binary fields are stored in an endian consistent manner if you plan on sharing data between different machine types. You will also want this data to have consistent size (use stdint.h types rather than int and long) and a canonical representation for things like floating point numbers.

Approach 1: We can Traverse the Tree twice:
First time to get the InOrder Traversal
SecondTime to get the PostOrder Traversal
Now By using these two lists at destination we can reconstruct the binary tree like follows:
public class ConstructBinaryTreeFromInorderAndPostorder {
int index;
public TreeNode buildTree( List<Integer> inOrder, List<Integer> postOrder) {
index = postOrder.size() - 1;
if (postOrder.size() == 1)
return new TreeNode(postOrder.get(0));
return constructTree(inOrder,postOrder, 0, postOrder.size() - 1);
}
public TreeNode constructTree(List<Integer> inOrder, List<Integer> postOrder, int start, int end) {
if (start > end) {
return null;
}
TreeNode root = new TreeNode(postOrder.get(index--));
if (start == end) {
return root;
}
int indexInInorder = search(inOrder, start, end, root.val);
root.right = constructTree(inOrder, postOrder, indexInInorder + 1, end);
root.left = constructTree(inOrder, postOrder, start, indexInInorder - 1);
return root;
}
public int search(List<Integer> inOrder, int strt, int end, int value) {
int i = 0;
for (i = strt; i <= end; i++) {
if (inOrder.get(i) == value)
return i;
}
return i;
}
public static void main(String[] args) {
List<Integer> inorder = Arrays.asList(2, 1, 3);
List<Integer> postOrder = Arrays.asList(2, 3, 1);
System.out.println(new ConstructBinaryTreeFromInorderAndPostorder().buildTree(inorder,postOrder ));
}
}
To Get the InOrder Traversal:
public class InorderTraversal {
void inOrderTraversal2(TreeNode node) {
if (node == null) {
return;
}
inOrderTraversal2(node.left);
System.out.println(node.val);
inOrderTraversal2(node.right);
}
}
To Get the PostOrder Traversal:
public class PostOrderTraversal {
void postOrderTraversal(TreeNode node) {
if (node == null) {
return;
}
postOrderTraversal(node.left);
postOrderTraversal(node.right);
System.out.println(node.val);
}
}
Approach 2:
We can save space by storing Preorder traversal and a marker for null pointers.
Let the marker for null pointers be '-1'
Input:
12
/
13
Output: 12 13 -1 -1
Input:
20
/ \
8 22
Output: 20 8 -1 -1 22 -1 -1
Input:
20
/
8
/ \
4 12
/ \
10 14
Output: 20 8 4 -1 -1 12 10 -1 -1 14 -1 -1 -1
Input:
20
/
8
/
10
/
5
Output: 20 8 10 5 -1 -1 -1 -1 -1
Input:
20
\
8
\
10
\
5
Output: 20 -1 8 -1 10 -1 5 -1 -1

Related

What is wrong with my insert function for min-heaps?

I'm trying to write a minimum heap data structure in C, but I ran into some issues while implementing the insert function.
It looks like this :
void insert(MinHeap* minh , int key)
{
if(minh->itemcount == minh->maxSize)
{
printf("cant insert,heap is full\n");
return;
}
minh->itemcount++;
minh->HeapArray[minh->itemcount]=key;
int parent=getParent(minh->itemcount);
while(parent != 0 && minh->HeapArray[parent] > minh->HeapArray[minh->itemcount])
{
swap(&(minh->HeapArray[parent]), &(minh->HeapArray[minh->itemcount]));
parent = parent/2;
}
}
Now the insertion process works if I insert the following values:
insert(minheap,5);
insert(minheap,3);
insert(minheap,2);
insert(minheap,4);
The output came out to be:
2 4 3 5
This is a valid output, since it follows the minimum heap property.
But once I start adding more values like 1, the output is:
2 1 3 5 4
As can you see, there is "bubbling up" of 1 occurring, but it doesn't seem to go all the way up, since 1 should be the first element, not 2.
I'm not sure why is this occurring, because my code for insertion has the same logic as any other minimum heap insertion function.
It would be great if anyone can help with clearing this up.
Some side notes:
MinHeap is a type-defined structure, and its members are :
typedef struct Heap
{
int* HeapArray;
int maxSize;
int itemcount;
} MinHeap;
I have a created an "instance" (with malloc) of this structure in the main function. I also dynamically allocated memory for the HeapArray Member. I also set the itemcount member to be equal to 0.
Also, the indexing for my minimum heap array starts with 1 not 0,
so the getParent function returns the following:
int getParent(int index)
{
return floor(index/2);
}
The main issue is that you are always swapping with the same element, i.e. with the last one at minh->HeapArray[minh->itemcount]: in the first iteration of the loop this is indeed the child of parent, but if there are more iterations, it no longer represents the child.
As a side issue: you have parent = parent / 2 in your loop: why didn't you use the getParent function here?
Secondly, the getParent function does not need to use floor: the division is already an integer division.
Here is the correction of where the main issue occurred:
int child = ++minh->itemcount;
minh->HeapArray[child] = key;
int parent = getParent(child);
while (parent != 0 && minh->HeapArray[parent] > minh->HeapArray[child]) {
swap(&(minh->HeapArray[parent]) , &(minh->HeapArray[child]));
child = parent;
parent = getParent(child);
}

Pointer to linkedlist randomly changing

For one of my school assignments I have to make my own stack library and a POSTFIX calculator.
The calculator has to make use of the stack library and do some calculations.
I am pushing two different numbers to my stack. Number 6 and 3. The header should point to the most recently added node (LIFO). So when 6 is added:
HEADER -> 6 -> NULL
When 3 is being added:
HEADER -> 3 -> 6 -> NULL
When I print the value of my header after adding '6' it's good. It's printing 6.
However, when I print the value of my header BEFORE adding '3' it's printing '3'. When it still should print 6.
So a summary of my problem:
When adding another node to my linkedlist, the header suddenly points to the newest node before even changing it.
You may understand me better with some code and debugging results.
Btw: Don't mind the typedefs, I don't like them. My teacher wants us to use it.
typedef struct stackObject* pStackObject_t;
typedef struct stackObject
{
void* obj;
pStackObject_t next;
} StackObject_t;
typedef struct stackMEta* pStackMeta_t;
typedef struct stackMEta
{
pStackObject_t stack;
size_t objsize;
int numelem; //number of elements
int handle; //welke stack
pStackMeta_t next;
} StackMeta_t;
int mystack_push(int handle, void* obj)
{
**DELETED NON RELATED CODE BASED ON FEEDBACK**
if (currentMeta->handle == handle)
{
pStackObject_t newObject = malloc(sizeof(StackObject_t));
newObject->obj = obj;
printf("%s%d\n", "Wanting to push int to stack: ", *(int*)obj);
//First node
if (currentMeta->stack == NULL)
{
currentMeta->stack = newObject;
currentMeta->stack->next = NULL;
printf("%s%d\n", " FIRST Curentmeta->stack pointing to ", *(int*)currentMeta->stack->obj);
return 0;
}
else
{
printf("%s%d\n", "NOT FIRST Currentmeta->stack pointing to ", *(int*)currentMeta->stack->obj);
newObject->next = currentMeta->stack;
currentMeta->stack = newObject;
printf("%s%d\n", "Currentmeta->stack ", *(int*)currentMeta->stack->obj);
printf("%s%d\n", "Currentmeta->stack->next ", *(int*)currentMeta->stack->next->obj);
printf("%s%d\n", "Succesful pushed int to stack: ", *(int*)currentMeta->stack->obj);
return 0;
}
}
return -1;
}
Terminal:
Created stack with handle: 1 and objsize 4 bytes
Wanting to push int to stack: 6
FIRST Curentmeta->stack pointing to 6
Wanting to push int to stack: 3
NOT FIRST Currentmeta->stack pointing to 3
Currentmeta->stack 3
Currentmeta->stack->next 3
Succesful pushed int to stack: 3
My unit tests are performing good with this code. My calculator does not, while it's the same function call.
I found out that it was working 50/50. Using the same input values in another program resulted in good things.
I changed the code to this:
pStackObject_t newObject = malloc(sizeof(StackObject_t));
newObject->obj = malloc(sizeof(currentMeta->objsize));
memcpy(newObject->obj, obj, currentMeta->objsize);
Now it's working fine. The previous code was somehow using the old values, while it was already out of scope. Thanks everyone for the help.

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.

Search and Inserting in a binary tree recursively

first of all happy new year. I was trying to fix a piece of code I've been stumped on for hours. (Note: I am not a solid coder.)
What I am trying to do is to write a function "searchInsert", which will take in a binary tree and some integer i. It will then try to find the integer i in the tree. If it's not there it is inserted into the tree.
Other information: If we do in fact find the integer in the tree, return a pointer pointing to the node of to it. If we do not find it as we said before, insert it in BUT return a pointer pointing to the root of the tree.
I also must do this recursively.
Now I have tested it using an arbitrary tree along with i = 98, as follows:
Before what it looks like.
4
/ \
2 6
/ \ / \
1 3 5 7
After, what it should look like:
4
/ \
2 6
/ \ / \
1 3 5 7
\
98
But my code doesn't seem to be working.
treelink searchInsert(treelink t, TreeItem i){
treelink keyNode = NULL;
if (t == NULL) {
t = insertTreeNode(t, i);
} else if(i < t->item){
keyNode = searchInsert(t->left,i);
} else if(i > t->item){
keyNode = searchInsert(t->right,i);
} else {
keyNode = t;
return keyNode;
}
return t;
}
Other important notes: treelink is a pointer to a binary tree. Assume insertTreeNode works as it was a function given to us.
Any help would be appreciated thanks.
Among other problems, you have lost all context when you realize that you have not found the item that you are looking for:
if ( t == NULL ) {
t = insertTreeNode(t, i) ;
}
So you are always calling insertTreeNode with NULL as the first argument.
While recursion is a great way to step through a tree, you might instead want to create a pointer and iterate through the tree, so that you have the original t around when you decide to call insert.
{
treelink ptr= t ;
while ( ptr )
{
if ( ptr-> item == i ) return ptr ;
ptr= ( ptr-> item > i ) ? ptr-> left : ptr-> right ;
}
return insertTreeNode( t, i ) ;
}
A new node is created, but it is not linked to the tree. You never change your left and right pointers.
what you need is to update the link after recursive call, e.g.:
else if (i < t->item) {
t->left = searchInsert(t->left, i);
} ...
But then of course you cannot simply return a pointer to a found item if it's found, otherwise it would break the tree. That's because the statement of your task is NOT recursive: you have to return either root or an existing (inner) node. So you might want to write a recursive function which e.g. always returns a pointer to the root, but also returns a pointer to a found item (through an additional treelink* argument).
Or maybe it would be simpler to split the function into two: search which returns a pointer to an existing node, and insert which returns a pointer to the root. Both of them would be recursive and quite simple.

Resources