0

I am trying to write code for serializing and deserializing a binary tree. I was successfully able to serialize the tree, however, I find it difficult to deserialize. (I am aware that many solutions are available. However, I prefer to learn on my own before I look them up)

Consider the tree below

      __1
     /   \
    2     3
   / \     \
  4   5     6
     

My serialization module outputs

[1, 2, 4, None, None, 5, None, None, 3, None, 6, None, None]

My code for the same is

def serialize(root):
    nodes = list()
    stack = [root]
    while len(stack):
        node = stack.pop()
        if node is not None: 
            nodes.append(node.value)
            if node.right: 
                stack.append(node.right)
            else:
                nodes.append(None)
            if node.left: 
                stack.append(node.left)
            else:
                nodes.append(None)
                
    return nodes
  • How do I deserialize without recursion?
  • Is there a recursive version of the deserialization?
  • The tree traversal I did, does it have a name?
  • Is there a recursive version of the serialization?

Any pointers to helpful material are also appreciated.

Dexter It
  • 3
  • 1
  • Please focus on one question only. You can always ask a new question. Did you try anything? Where are you stuck? – trincot Mar 28 '21 at 10:07

1 Answers1

0

You really should only ask one question, so I will focus on the deserialization only:

How do I deserialize without recursion?

Like your non-recursive solution for serialising, you'll need a stack. You also need to know whether the current value is intended for a left or for a right child. You can know this from the preceding input value. It it was None, than it means the next value is always for a right child. If not, then it always means we just created a parent Node, and the current value is about its left child.

Also, the algorithm is a bit easier when you start with a dummy parent node of the root, so that the tree is built as its left-side subtree:

def deserialize(data):
    stack = []
    prev_value = 1  # dummy value, can be anything, but not None
    parent = node = Node(prev_value)  # dummy node, whose left child will be the result
    for value in data:
        if value is None:
            if node.left is not None or prev_value is None:
                # Current None is about right child. Go up...
                node = stack.pop()
                while node.right is not None:
                    node = stack.pop()
        else:  # going down...
            stack.append(node)
            if prev_value is None:  # ...after going up
                node.right = Node(value)
                node = node.right
            else:
                node.left = Node(value)
                node = node.left
        prev_value = value
    return parent.left

Is there a recursive version of the deserialization?

Yes, there is, and it requires less code:

def deserialize(data):
    it = iter(data)

    def recur():
        value = next(it)
        return None if value is None else Node(value, recur(), recur())
    
    return recur()

The above code assumes that you have a Node constructor that accepts (optional) arguments for its left and right properties:

class Node:
    def __init__(self, value, left=None, right=None):
        self.value = value
        self.left = left
        self.right = right

The tree traversal I did, does it have a name?

Yes, it is a preorder traversal.

Is there a recursive version of the serialization?

Yes there is. Have a go at it. If you bump into an issue in creating such a version, then dedicate a separate question on that.

trincot
  • 317,000
  • 35
  • 244
  • 286
  • 1
    Thanks, really appreciate the help. Took me a while to wrap my head around what you wrote. But, good learning experience. I came close but never could complete it. I was stuck in the point where you mentioned two consecutive "None" means next is a right node. – Dexter It Mar 30 '21 at 18:22