How to Serialize Binary Tree

后端 未结 10 845
野的像风
野的像风 2020-12-23 21:09

I went to an interview today where I was asked to serialize a binary tree. I implemented an array-based approach where the children of node i (numbering in level-order trave

相关标签:
10条回答
  • 2020-12-23 21:26

    I am not using pre-order but I am using BFS. This is a question from leetcode

    Majority of people implementation are incorrect when using pre-order: the expected result should be

    "[1,2,3,null,null,4,5]", but instead majority people print the output as "[1,2,3,null,null,4,5,null,null]" since they are not counting the levels.

    Here is my implementation with the correct result.

    class Node(object):
        def __init__(self,data):
            self.left = None
            self.right = None
            self.data = data
    
    def serialize(root):
            queue = [(root,0)]
            result = []
            max_level_with_value = 0
            while queue:
                (node,l) = queue.pop(0)
                if node:
                    result.append((node.data,l))
                    queue.extend([(node.left,l+1),
                                  (node.right,l+1)
                                  ])
                    max_level_with_value = max(max_level_with_value,l)
                else:
                    result.append(('null',l))
            filter_redundant(result,max_level_with_value)
    
    
    def filter_redundant(result,max_level_with_value):
        for v,l in result:
            if l<= max_level_with_value:
                print(v)
    
    
    
    
    root = Node(1)
    root.left = Node(2)
    root.right = Node(3)
    root.right.left = Node(4)
    root.right.right = Node(5)
    serialize(root)
    
    0 讨论(0)
  • 2020-12-23 21:31

    convert it to array with size of (2n + 1) each left son and right son will be in place of (2 * node number) and ((2 * node number) + 1 accordingly.

    using https://www-inst.eecs.berkeley.edu//~cs61bl/r/cur/trees/array-repr.html?topic=lab20.topic&step=1&course=

    0 讨论(0)
  • 2020-12-23 21:33

    All those articles talk mostly about the serialization part. The deserialization part is slightly tricky to do in one pass.

    I have implemented an efficient solution for deserialization too.

    Problem: Serialize and Deserialize a binary tree containing positive numbers.

    Serialization part:

    1. Use 0 to represent null.
    2. Serialize to list of integers using preorder traversal.

    Deserialization part:

    1. Takes in list of integers and uses recursive helper method for deserialization.
    2. Recursive deserializer returns a pair (BTNode node, int nextIndexToRead) where node is tree node constructed so far, and nextIndexToRead is position of next number to be read in the serialized list of numbers.

    Below is the code in Java:

    public final class BinaryTreeSerializer
    {
        public static List<Integer> Serialize(BTNode root)
        {
            List<Integer> serializedNums = new ArrayList<Integer>();
    
            SerializeRecursively(root, serializedNums);
    
            return serializedNums;
        }
    
        private static void SerializeRecursively(BTNode node, List<Integer> nums)
        {
            if (node == null)
            {
                nums.add(0);
                return;
            }
    
            nums.add(node.data);
            SerializeRecursively(node.left, nums);
            SerializeRecursively(node.right, nums);
        }
    
        public static BTNode Deserialize(List<Integer> serializedNums)
        {
            Pair pair = DeserializeRecursively(serializedNums, 0);
    
            return pair.node;
        }
    
        private static Pair DeserializeRecursively(List<Integer> serializedNums, int start)
        {        
            int num = serializedNums.get(start);
    
            if (num == 0)
            {
                return new Pair(null, start + 1);
            }
    
            BTNode node = new BTNode(num);
    
            Pair p1 = DeserializeRecursively(serializedNums, start + 1);
            node.left = p1.node;
    
            Pair p2 = DeserializeRecursively(serializedNums, p1.startIndex);
            node.right = p2.node;
    
            return new Pair(node, p2.startIndex);
        }
    
        private static final class Pair
        {
            BTNode node;
            int startIndex;
    
            private Pair(BTNode node, int index)
            {
                this.node = node;
                this.startIndex = index;
            }
        }
    }
    
    public class BTNode 
    {
        public int data;
        public BTNode left;
        public BTNode right;
    
        public BTNode(int data)
        {
            this.data = data;
        }
    }
    
    0 讨论(0)
  • 2020-12-23 21:38

    The best way is to use a special char (like # as previous comment mentioned) as sentinel. It's better than constructing an inorder traversal array and a preorder/postorder traversal array, both in space complexity wise and time complexity wise. it's also way easier to implement.

    Linked list is not a good fit here since in order to reconstruct the tree, you better have const element access time

    0 讨论(0)
  • 2020-12-23 21:41

    Here is a late answer in Python. It uses (depth-first) preorder serialization and returns a list of strings. Deserialization returns the tree.

    class Node:
        def __init__(self, val, left=None, right=None):
            self.val = val
            self.left = left
            self.right = right
    
    
    # This method serializes the tree into a string
    def serialize(root):
        vals = []
        def encode(node):
            vals.append(str(node.val))
            if node.left is not None:
                encode(node.left)
            else:
                vals.append("L")
            if node.right is not None:
                encode(node.right)
            else:
                vals.append("R")
        encode(root)
        print(vals)
        return vals
    
    
    # This method deserializes the string back into the tree
    def deserialize(string_list):
        def create_a_tree(sub_list):
            if sub_list[0] == 'L' or sub_list[0] == 'R':
                del sub_list[0]
                return None
            parent = Node(sub_list[0])
            del sub_list[0]
            parent.left = create_a_tree(sub_list)
            parent.right = create_a_tree(sub_list)
            return parent
        if len(string_list) != 0:
            root_node = create_a_tree(string_list)
        else:
            print("ERROR - empty string!")
            return 0
        return root_node
    

    To test:

    tree1 = Node('root', Node('left'), Node('right'))
    t = deserialize(serialize(tree1))
    print(str(t.right.val))
    
    0 讨论(0)
  • 2020-12-23 21:42

    How about performing an in-order traversal and putting the root key and all node keys into a std::list or other container of your choice which flattens the tree. Then, simply serialize the std::list or container of your choice using the boost library.

    The reverse is simple and then rebuild the tree using standard insertion to a binary tree. This may not be entirely efficient for a very large tree but runtime to convert the tree into a std::list is O(n) at most and to rebuild the tree is O(log n) at most.

    I am about to do this to serialize a tree I just coded up in c++ as I am converting my database from Java to C++.

    0 讨论(0)
提交回复
热议问题