3

I recently faced this question during the interview and the interviewer asking me to create two function. Function1 should take the n-ary tree and convert to byte array and function2 should take the byte[] and build the n-ary tree. If it was a binary tree, i would have made pre-order traversal with the special character for null and stored in an array and converted to byte[] but here n-ary tree (with many children). I don't know how to store this and rebuild the n-ary tree with an array. Any ideas or formula to store this n-ary tree into array?. I appreciate your help.

karthickeyan
  • 91
  • 1
  • 6

4 Answers4

2

Looks to me like a good use for recursion. Write a method (subroutine, function) that writes out one node and all the tree below it. It would write out the node, then write out the number of children (zero for leaf nodes), then call itself to write each child if there are any. Now call the method on the top node in the tree and you've serialized it.

To deserialize, write a method that reads in a node. It would read in the node itself, read in the number of child nodes, then read in each child node, if any. Call it once on the stream and it will hand you the top node with all the descendant nodes in place--the entire tree.

The moral of this story is that recursion (which is really just a convenient way to get and use a stack) is really useful for working with graphs. And a lot more things than you might think are graphs.

RalphChapin
  • 2,874
  • 13
  • 17
2

It is needed to distinguish between two cases: 1. complete n-ary Trees and 2. sparse n-ary or non-Complete Trees. In the first case, assuming that N=5 so each level i in the Tree will have exactly (i.e. no less, no more) 5^i nodes; on the other hand, in the second case, this rule isn't valid since the Tree can be filled randomly by construction.

Complete n-ary Trees can be serialized into an array; simply extending from the complete Binary Search Tree: nodes (intermediary and leaves) are related each other by the level i and the actual N by the forum Ni+1+c* where c is the c-th child. Adopting a level-order traversal, the Tree can be optimally serialized in an array of bytes (no further characters are needed, read hereafter). Here a comprehensive explanation.

Unfortunately, for the non-Complete n-ary Trees, as anticipated, the above formula doesn't apply. Therefore a different approach needs to be adopted. One approach would consist in serializing special characters indicating the absence of children, or better serializing the NULL values of the children pointers. This approach is not optimal, since a further number of characters are needed (totally N additional bytes are needed) but it's a pretty straightforward and viable one. Let's examine an example:

       A
     / | \ 
    B  C  D
   / \     \
  E   F     G

adopting a pre-order traversal, the above non-Complete n-ary Tree is serialized as follows

 A B E / F / / C / D G / / /

the '/' maps the NULL and provides the ability to deserialize the Tree into the original one. A pre-order traversal is adopted to visit the Tree and output the above array of characters. In total *2*N* bytes are serialized, since in that case the Tree values are exactly 1 character each. As deserialization algorithm, still the pre-order traversal can be adopted: few modifications are needed to recognize the NULLs mapping pattern, as above represented. A C++ code example is here.

Concluding, serializing and deserializing a non-Complete or sparse n-ary Tree is a bit more tricky and needs a further amount of bytes to forcely map the NULLs.

Paolo Maresca
  • 6,558
  • 4
  • 31
  • 28
0

Actually wikipedia helped me to find solution. I am able to store the n-ary tree into array and convert into byte[] and then convert the byte[] back to array using the below formula c-th child is found at index k*i + 1 + c parent is found at index i -1/2

karthickeyan
  • 91
  • 1
  • 6
  • That's true only in case the n-ary Tree is complete. When the n-ary Tree is not complete or balanced, such formula isn't valid. A different approach is needed: a naive approach would consist in storing an 'end' character to control the recursion, here[1] an idea. [1] http://www.geeksforgeeks.org/serialize-deserialize-n-ary-tree/ – Paolo Maresca Feb 22 '15 at 18:40
0

Here is the code, BFS + Queue, should be straight forward to read.

class Node:
    def __init__(self, val):
        self.val = val 
        self.children = []

class Codec:
    def serialize(self, root):
        if root is None:
            return ""
        res = [root.val, "#"]
        q = collections.deque([root])
        while q:
            node = q.popleft()
            for child in node.children:
                res.append(child.val)
                q.append(child)
            res.append("#")
        return ",".join(res)

    def deserialize(self, s):
        if len(s) == 0:
            return
        vals = s.split(",")
        q = collections.deque()
        root = Node(vals[0])
        q.append(root)
        i = 1
        while q:
            node = q.popleft()
            i += 1
            while vals[i] != "#":
                child = Node(vals[i])
                node.children.append(child)
                q.append(child)
                i += 1
        return root
Charlie 木匠
  • 1,450
  • 12
  • 18