Serialization 如何序列化二叉树

Serialization 如何序列化二叉树,serialization,tree,binary-tree,flatten,binary-search-tree,Serialization,Tree,Binary Tree,Flatten,Binary Search Tree,今天我参加了一次采访,采访中我被要求序列化一棵二叉树。我实现了一种基于数组的方法,其中节点I的子节点(按级别顺序遍历编号)位于左子节点的2*I索引处,右子节点的2*I+1处。面试官似乎多少有些高兴,但我想知道连载到底是什么意思?它是否特别适用于扁平化树以写入磁盘,或者序列化树是否还包括将树转换为链接列表,例如。此外,我们如何将树展平为(双重)链表,然后重建它?您能从链表中重新创建树的确切结构吗?方法1: 执行按序和按序遍历以对树数据进行序列化。 在反序列化时,使用Pre-order和do-BST

今天我参加了一次采访,采访中我被要求序列化一棵二叉树。我实现了一种基于数组的方法,其中节点I的子节点(按级别顺序遍历编号)位于左子节点的2*I索引处,右子节点的2*I+1处。面试官似乎多少有些高兴,但我想知道连载到底是什么意思?它是否特别适用于扁平化树以写入磁盘,或者序列化树是否还包括将树转换为链接列表,例如。此外,我们如何将树展平为(双重)链表,然后重建它?您能从链表中重新创建树的确切结构吗?

方法1: 执行按序和按序遍历以对树数据进行序列化。 在反序列化时,使用Pre-order和do-BST-On以正确地形成树

您需要两者,因为A->B->C可以表示为预订单,即使结构可能不同

方法2:
将#用作左侧或右侧子级为空的哨兵…

执行顺序遍历,并将根键和所有节点键放入std::list或您选择的其他容器中,以展平树。然后,使用boost库简单地序列化您选择的std::list或容器

相反的方法很简单,然后使用二叉树的标准插入来重建树。对于非常大的树,这可能不是完全有效的,但将树转换为std::list的运行时最多为O(n),重建树的运行时最多为O(logn)


<>我将要做的就是将一个刚在C++中编码的树,我把数据库从java转换成C++。

所有的文章都主要讨论序列化部分。反序列化部分在一个过程中完成有点棘手

我还实现了一个反序列化的有效解决方案

问题:序列化和反序列化包含正数的二叉树。

序列化部分:

  • 使用0表示null
  • 使用前序遍历序列化为整数列表
  • 反序列化部分:

  • 接受整数列表并使用递归帮助器方法进行反序列化
  • 递归反序列化器返回一对(BTNode node,int nextIndexToRead),其中node是到目前为止构造的树节点,nextIndexToRead是要在序列化的数字列表中读取的下一个数字的位置
  • 下面是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;
        }
    }
    
    公共最终类二进制树序列化程序
    {
    公共静态列表序列化(BTNode root)
    {
    List serializedNums=new ArrayList();
    以递归方式序列化(根,序列化dnums);
    返回序列dnums;
    }
    递归地序列化私有静态void(BTNode节点,List nums)
    {
    if(node==null)
    {
    nums.add(0);
    返回;
    }
    添加(node.data);
    递归序列化(node.left,nums);
    递归序列化(node.right,nums);
    }
    公共静态BTNode反序列化(列表序列化)
    {
    Pair Pair=反序列化安全地(序列化数,0);
    返回pair.node;
    }
    私有静态对反序列化安全(列出序列化的dnum,int start)
    {        
    int num=serializedNums.get(开始);
    如果(num==0)
    {
    返回新对(空,开始+1);
    }
    BTNode节点=新的BTNode(num);
    对p1=反序列化安全(序列化数,开始+1);
    node.left=p1.node;
    p2对=反序列化安全(序列化dnums,p1.startIndex);
    node.right=p2.node;
    返回新的对(节点,p2.startIndex);
    }
    私有静态最终类对
    {
    BTNode节点;
    国际标准指数;
    专用对(BTNode节点,int索引)
    {
    this.node=节点;
    this.startIndex=索引;
    }
    }
    }
    公共类BTNode
    {
    公共int数据;
    公共BTNode左;
    公共节点权;
    公共BTNode(int数据)
    {
    这个数据=数据;
    }
    }
    
    最好的方法是使用一个特殊的字符(如前面的评论所述)作为哨兵。在空间复杂度和时间复杂度方面,它都比构造一个有序遍历数组和一个前序/后序遍历数组要好。它也更容易实现


    链表在这里不太合适,因为为了重建树,最好使用预顺序遍历、序列化二叉树来获得常量元素访问时间。 使用相同的预顺序遍历来反序列化树。小心边缘的情况。此处,空节点由“#”表示


    我一直在想它的要点。这是我的Java实现。如前所述,这是一个二叉树而不是BST。对于序列化,前序遍历似乎更容易(对于空节点,使用带有“NULL”的字符串)。请用递归调用的完整示例检查下面的代码。对于反序列化,字符串将转换为LinkedList,其中remove(0)在O(1)运行时获取顶部元素。还请参见反序列化代码注释中的完整示例。希望这能帮助一些人比我少挣扎:) 每个方法(序列化和反序列化)的总运行时间与二叉树遍历的运行时间相同,即O(n),其中n是树中的节点数(条目)

    import java.util.LinkedList;
    import java.util.List;
    
    public class SerDesBinTree<T> {
    
        public static class TreeEntry<T>{
            T element;
            TreeEntry<T> left;
            TreeEntry<T> right;
            public TreeEntry(T x){
                element = x;
                left = null;
                right = null;
            }
        }
    
        TreeEntry<T> root;
        int size;
        StringBuilder serSB = new StringBuilder();
        List<String> desList = new LinkedList<>();
    
        public SerDesBinTree(){
            root = null;
            size = 0;   
        }
    
        public void traverseInOrder(){
            traverseInOrder(this.root);
        }
    
        public void traverseInOrder(TreeEntry<T> node){
            if (node != null){
                traverseInOrder(node.left);
                System.out.println(node.element);
                traverseInOrder(node.right);
            }
        }
    
        public void serialize(){
            serialize(this.root);
        }
    
    
        /*
         *          1
         *         / \
         *        2   3
         *           /
         *          4 
         *        
         *        ser(1)                              
         *            serSB.append(1)                     serSB: 1
         *            ser(1.left)
         *            ser(1.right)
         *            |
         *            |
         *            ser(1.left=2)
         *                serSB.append(2)                 serSB: 1, 2
         *                ser(2.left)
         *                ser(2.right)
         *                |
         *                |
         *                ser(2.left=null)
         *                    serSB.append(NULL)          serSB: 1, 2, NULL
         *                    return
         *                |    
         *                ser(2.right=null)
         *                    serSB.append(NULL)          serSB: 1, 2, NULL, NULL
         *                    return
         *                    
         *             |
         *             ser(1.right=3)
         *                serSB.append(3)                 serSB: 1, 2, NULL, NULL, 3
         *                ser(3.left)
         *                ser(3.right)
         *                
         *                |
         *                ser(3.left=4)
         *                    serSB.append(4)             serSB: 1, 2, NULL, NULL, 3, 4
         *                    ser(4.left)
         *                    ser(4.right)
         *                    
         *                    |
         *                    ser(4.left=null)
         *                        serSB.append(NULL)      serSB: 1, 2, NULL, NULL, 3, 4, NULL
         *                        return
         *                        
         *                    ser(4.right=null)
         *                        serSB.append(NULL)      serSB: 1, 2, NULL, NULL, 3, 4, NULL, NULL
         *                        return
         *                        
         *                ser(3.right=null)
         *                    serSB.append(NULL)          serSB: 1, 2, NULL, NULL, 3, 4, NULL, NULL, NULL
         *                    return
         *        
         */
        public void serialize(TreeEntry<T> node){
            // preorder traversal to build the string
            // in addition: NULL will be added (to make deserialize easy)
            // using StringBuilder to append O(1) as opposed to
            // String which is immutable O(n)
            if (node == null){
                serSB.append("NULL,");
                return;
            }
    
            serSB.append(node.element + ",");
            serialize(node.left);
            serialize(node.right);
        }
    
        public TreeEntry<T> deserialize(TreeEntry<T> newRoot){
            // convert the StringBuilder into a list
            // so we can do list.remove() for the first element in O(1) time
    
            String[] desArr = serSB.toString().split(",");
    
            for (String s : desArr){
                desList.add(s);
            }
    
    
            return deserialize(newRoot, desList);
        }
    
    
        /*
         *          1
         *         / \
         *        2   3
         *           /
         *          4 
         * 
         *        deser(root, list)                              list: 1, 2, NULL, NULL, 3, 4, NULL, NULL, NULL
         *            root = new TreeEntry(1)                    list: 2, NULL, NULL, 3, 4, NULL, NULL, NULL
         *            root.left = deser(root.left, list)  // **
         *            root.right = deser(root.right, list) // *-*
         *            return root // ^*^
         *            
         *            
         *      so far subtree
         *          1
         *         / \
         *      null  null
         *            
         *            deser(root.left, list)
         *                 root.left = new TreeEntry(2)          list: NULL, NULL, 3, 4, NULL, NULL, NULL
         *                 root.left.left = deser(root.left.left, list) // ***
         *                 root.left.right = deser(root.left.right, list)  // ****
         *                 return root.left // eventually return new TreeEntry(2) to ** above after the two calls are done
         *                 
         *           so far subtree
         *                 2
         *                / \
         *            null   null 
         *                 
         *                 deser(root.left.left, list)      
         *                     // won't go further down as the next in list is NULL
         *                      return null    // to ***                    list: NULL, 3, 4, NULL, NULL, NULL
         *                      
         *           so far subtree (same, just replacing null)
         *                 2
         *                / \
         *            null   null 
         *            
         *                 deser(root.left.right, list)
         *                     // won't go further down as the next in list is NULL
         *                      return null    // to ****                 list: 3, 4, NULL, NULL, NULL
         *                      
         *           so far subtree (same, just replacing null)
         *                 2
         *                / \
         *            null   null 
         *            
         *      
         *      so far subtree // as node 2 completely returns to ** above
         *          1
         *         / \
         *        2  null
         *       / \
         *   null   null
         *      
         *      
         *            deser(root.right, list)
         *                 root.right = new TreeEntry(3)                list: 4, NULL, NULL, NULL
         *                 root.right.left = deser(root.right.left, list) // *&*
         *                 root.right.right = deser(root.right.right, list)  // *---*
         *                 return root.right // eventually return to *-* above after the previous two calls are done
         *                 
         *           so far subtree
         *                 3
         *                / \
         *            null   null 
         *            
         *            
         *                 deser(root.right.left, list)
         *                      root.right.left = new TreeEntry(4)       list: NULL, NULL, NULL
         *                      root.right.left.left = deser(root.right.left.left, list) // *(*
         *                      root.right.left.right = deser(root.right.left.right, list) // *)*
         *                      return root.right.left // to *&*
         *                      
         *                  so far subtree
         *                       4
         *                      / \
         *                  null   null 
         *                    
         *                       deser(root.right.left.left, list)
         *                             // won't go further down as the next in list is NULL
         *                             return null // to *(*         list: NULL, NULL
         *                             
         *                  so far subtree (same, just replacing null)
         *                       4
         *                      / \
         *                  null   null 
         *                  
         *                       deser(root.right.left.right, list)
         *                             // won't go further down as the next in list is NULL
         *                             return null // to *)*         list: NULL
         *                             
         *                             
         *                  so far subtree (same, just replacing null)
         *                       4
         *                      / \
         *                  null   null 
         *                  
         *                  
         *           so far subtree
         *                 3
         *                / \
         *               4   null   
         *              / \
         *           null  null
         *                
         *                
         *                deser(root.right.right, list)
         *                        // won't go further down as the next in list is NULL
         *                       return null // to *---*    list: empty
         *                       
         *           so far subtree (same, just replacing null of the 3 right)
         *                 3
         *                / \
         *               4   null   
         *              / \
         *           null  null   
         *           
         *           
         *           now returning the subtree rooted at 3 to root.right in *-*
         *           
         *          1
         *         / \
         *        /   \
         *       /     \
         *      2       3
         *     / \     / \
         * null  null /   null
         *           /
         *          4
         *         / \
         *      null  null 
         *      
         *      
         *      finally, return root (the tree rooted at 1) // see ^*^ above
         *    
         */
        public TreeEntry<T> deserialize(TreeEntry<T> node, List<String> desList){
    
            if (desList.size() == 0){
                return null;
            }
    
            String s = desList.remove(0); // efficient operation O(1)
            if (s.equals("NULL")){
                return null;
            }
    
            Integer sInt = Integer.parseInt(s);
            node = new TreeEntry<T>((T)sInt);
    
            node.left = deserialize(node.left, desList);
            node.right = deserialize(node.right, desList);
    
            return node;
        }
    
    
        public static void main(String[] args) {
            /*
             *          1
             *         / \
             *        2   3
             *           /
             *          4 
             *        
             */
            SerDesBinTree<Integer> tree = new SerDesBinTree<>();
            tree.root = new TreeEntry<Integer>(1);
            tree.root.left = new TreeEntry<Integer>(2);
            tree.root.right = new TreeEntry<Integer>(3);
            tree.root.right.left = new TreeEntry<Integer>(4);
            //tree.traverseInOrder();
    
            tree.serialize();
            //System.out.println(tree.serSB);
    
            tree.root = null;
            //tree.traverseInOrder();
    
            tree.root = tree.deserialize(tree.root);
            //tree.traverseInOrder();
    
            // deserialize into a new tree
            SerDesBinTree<Integer> newTree = new SerDesBinTree<>();
            newTree.root = tree.deserialize(newTree.root);
            newTree.traverseInOrder();
    
    
        }
    }
    
    import java.util.LinkedList;
    导入java.util.List;
    公共类蛇形树{
    公共静态类树{
    T元素;
    树左;
    树右;
    公树(TX){
    元素=x;
    左=空;
    右=空;
    }
    }
    树根;
    整数大小;
    StringBuilder serSB=新的StringBuilder();
    List desList=新建链接列表();
    公蛇树(){
    root=null;
    
    import java.util.LinkedList;
    import java.util.List;
    
    public class SerDesBinTree<T> {
    
        public static class TreeEntry<T>{
            T element;
            TreeEntry<T> left;
            TreeEntry<T> right;
            public TreeEntry(T x){
                element = x;
                left = null;
                right = null;
            }
        }
    
        TreeEntry<T> root;
        int size;
        StringBuilder serSB = new StringBuilder();
        List<String> desList = new LinkedList<>();
    
        public SerDesBinTree(){
            root = null;
            size = 0;   
        }
    
        public void traverseInOrder(){
            traverseInOrder(this.root);
        }
    
        public void traverseInOrder(TreeEntry<T> node){
            if (node != null){
                traverseInOrder(node.left);
                System.out.println(node.element);
                traverseInOrder(node.right);
            }
        }
    
        public void serialize(){
            serialize(this.root);
        }
    
    
        /*
         *          1
         *         / \
         *        2   3
         *           /
         *          4 
         *        
         *        ser(1)                              
         *            serSB.append(1)                     serSB: 1
         *            ser(1.left)
         *            ser(1.right)
         *            |
         *            |
         *            ser(1.left=2)
         *                serSB.append(2)                 serSB: 1, 2
         *                ser(2.left)
         *                ser(2.right)
         *                |
         *                |
         *                ser(2.left=null)
         *                    serSB.append(NULL)          serSB: 1, 2, NULL
         *                    return
         *                |    
         *                ser(2.right=null)
         *                    serSB.append(NULL)          serSB: 1, 2, NULL, NULL
         *                    return
         *                    
         *             |
         *             ser(1.right=3)
         *                serSB.append(3)                 serSB: 1, 2, NULL, NULL, 3
         *                ser(3.left)
         *                ser(3.right)
         *                
         *                |
         *                ser(3.left=4)
         *                    serSB.append(4)             serSB: 1, 2, NULL, NULL, 3, 4
         *                    ser(4.left)
         *                    ser(4.right)
         *                    
         *                    |
         *                    ser(4.left=null)
         *                        serSB.append(NULL)      serSB: 1, 2, NULL, NULL, 3, 4, NULL
         *                        return
         *                        
         *                    ser(4.right=null)
         *                        serSB.append(NULL)      serSB: 1, 2, NULL, NULL, 3, 4, NULL, NULL
         *                        return
         *                        
         *                ser(3.right=null)
         *                    serSB.append(NULL)          serSB: 1, 2, NULL, NULL, 3, 4, NULL, NULL, NULL
         *                    return
         *        
         */
        public void serialize(TreeEntry<T> node){
            // preorder traversal to build the string
            // in addition: NULL will be added (to make deserialize easy)
            // using StringBuilder to append O(1) as opposed to
            // String which is immutable O(n)
            if (node == null){
                serSB.append("NULL,");
                return;
            }
    
            serSB.append(node.element + ",");
            serialize(node.left);
            serialize(node.right);
        }
    
        public TreeEntry<T> deserialize(TreeEntry<T> newRoot){
            // convert the StringBuilder into a list
            // so we can do list.remove() for the first element in O(1) time
    
            String[] desArr = serSB.toString().split(",");
    
            for (String s : desArr){
                desList.add(s);
            }
    
    
            return deserialize(newRoot, desList);
        }
    
    
        /*
         *          1
         *         / \
         *        2   3
         *           /
         *          4 
         * 
         *        deser(root, list)                              list: 1, 2, NULL, NULL, 3, 4, NULL, NULL, NULL
         *            root = new TreeEntry(1)                    list: 2, NULL, NULL, 3, 4, NULL, NULL, NULL
         *            root.left = deser(root.left, list)  // **
         *            root.right = deser(root.right, list) // *-*
         *            return root // ^*^
         *            
         *            
         *      so far subtree
         *          1
         *         / \
         *      null  null
         *            
         *            deser(root.left, list)
         *                 root.left = new TreeEntry(2)          list: NULL, NULL, 3, 4, NULL, NULL, NULL
         *                 root.left.left = deser(root.left.left, list) // ***
         *                 root.left.right = deser(root.left.right, list)  // ****
         *                 return root.left // eventually return new TreeEntry(2) to ** above after the two calls are done
         *                 
         *           so far subtree
         *                 2
         *                / \
         *            null   null 
         *                 
         *                 deser(root.left.left, list)      
         *                     // won't go further down as the next in list is NULL
         *                      return null    // to ***                    list: NULL, 3, 4, NULL, NULL, NULL
         *                      
         *           so far subtree (same, just replacing null)
         *                 2
         *                / \
         *            null   null 
         *            
         *                 deser(root.left.right, list)
         *                     // won't go further down as the next in list is NULL
         *                      return null    // to ****                 list: 3, 4, NULL, NULL, NULL
         *                      
         *           so far subtree (same, just replacing null)
         *                 2
         *                / \
         *            null   null 
         *            
         *      
         *      so far subtree // as node 2 completely returns to ** above
         *          1
         *         / \
         *        2  null
         *       / \
         *   null   null
         *      
         *      
         *            deser(root.right, list)
         *                 root.right = new TreeEntry(3)                list: 4, NULL, NULL, NULL
         *                 root.right.left = deser(root.right.left, list) // *&*
         *                 root.right.right = deser(root.right.right, list)  // *---*
         *                 return root.right // eventually return to *-* above after the previous two calls are done
         *                 
         *           so far subtree
         *                 3
         *                / \
         *            null   null 
         *            
         *            
         *                 deser(root.right.left, list)
         *                      root.right.left = new TreeEntry(4)       list: NULL, NULL, NULL
         *                      root.right.left.left = deser(root.right.left.left, list) // *(*
         *                      root.right.left.right = deser(root.right.left.right, list) // *)*
         *                      return root.right.left // to *&*
         *                      
         *                  so far subtree
         *                       4
         *                      / \
         *                  null   null 
         *                    
         *                       deser(root.right.left.left, list)
         *                             // won't go further down as the next in list is NULL
         *                             return null // to *(*         list: NULL, NULL
         *                             
         *                  so far subtree (same, just replacing null)
         *                       4
         *                      / \
         *                  null   null 
         *                  
         *                       deser(root.right.left.right, list)
         *                             // won't go further down as the next in list is NULL
         *                             return null // to *)*         list: NULL
         *                             
         *                             
         *                  so far subtree (same, just replacing null)
         *                       4
         *                      / \
         *                  null   null 
         *                  
         *                  
         *           so far subtree
         *                 3
         *                / \
         *               4   null   
         *              / \
         *           null  null
         *                
         *                
         *                deser(root.right.right, list)
         *                        // won't go further down as the next in list is NULL
         *                       return null // to *---*    list: empty
         *                       
         *           so far subtree (same, just replacing null of the 3 right)
         *                 3
         *                / \
         *               4   null   
         *              / \
         *           null  null   
         *           
         *           
         *           now returning the subtree rooted at 3 to root.right in *-*
         *           
         *          1
         *         / \
         *        /   \
         *       /     \
         *      2       3
         *     / \     / \
         * null  null /   null
         *           /
         *          4
         *         / \
         *      null  null 
         *      
         *      
         *      finally, return root (the tree rooted at 1) // see ^*^ above
         *    
         */
        public TreeEntry<T> deserialize(TreeEntry<T> node, List<String> desList){
    
            if (desList.size() == 0){
                return null;
            }
    
            String s = desList.remove(0); // efficient operation O(1)
            if (s.equals("NULL")){
                return null;
            }
    
            Integer sInt = Integer.parseInt(s);
            node = new TreeEntry<T>((T)sInt);
    
            node.left = deserialize(node.left, desList);
            node.right = deserialize(node.right, desList);
    
            return node;
        }
    
    
        public static void main(String[] args) {
            /*
             *          1
             *         / \
             *        2   3
             *           /
             *          4 
             *        
             */
            SerDesBinTree<Integer> tree = new SerDesBinTree<>();
            tree.root = new TreeEntry<Integer>(1);
            tree.root.left = new TreeEntry<Integer>(2);
            tree.root.right = new TreeEntry<Integer>(3);
            tree.root.right.left = new TreeEntry<Integer>(4);
            //tree.traverseInOrder();
    
            tree.serialize();
            //System.out.println(tree.serSB);
    
            tree.root = null;
            //tree.traverseInOrder();
    
            tree.root = tree.deserialize(tree.root);
            //tree.traverseInOrder();
    
            // deserialize into a new tree
            SerDesBinTree<Integer> newTree = new SerDesBinTree<>();
            newTree.root = tree.deserialize(newTree.root);
            newTree.traverseInOrder();
    
    
        }
    }
    
    For example:
    
    You may serialize the following tree:
    
        1
       / \
      2   3
         / \
        4   5
    
    as "[1,2,null,null,3,4,null,null,5,null,null,]"
    
     /**
     * Definition for a binary tree node.
     * public class TreeNode {
     *     int val;
     *     TreeNode left;
     *     TreeNode right;
     *     TreeNode(int x) { val = x; }
     * }
     */
    public class Codec {
    
        // Encodes a tree to a single string.
        public String serialize(TreeNode root) {
    
            if(root == null)
                return "X,";
    
            String leftSerialized = serialize(root.left);
            String rightSerialized = serialize(root.right);
    
            return root.val + "," + leftSerialized + rightSerialized;
        }
    
        private TreeNode deserializeHelper(Queue<String> queue)
        {
            String nodeValue = queue.poll();
    
            if(nodeValue.equals("X"))
                return null;
    
            TreeNode newNode = new TreeNode(Integer.valueOf(nodeValue));
    
            newNode.left = deserializeHelper(queue);
            newNode.right = deserializeHelper(queue);
    
            return newNode;
        }
    
        // Decodes your encoded data to tree.
        public TreeNode deserialize(String data) {
    
            Queue<String> queue = new LinkedList<>();
            queue.addAll(Arrays.asList(data.split(",")));
    
            return deserializeHelper(queue);
        }
    }
    
    //Codec object will be instantiated and called as such:
    //Codec codec = new Codec();
    //codec.deserialize(codec.serialize(root));
    
    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)
    
        public class CodecNry {
    
        class Node {
            public int val;
            public List<Node> children;
            public Node(int _val, List<Node> _children) {
                val = _val;
                children = _children;
            }
        }
    
        public String serialize(Node root) {
            if (root == null) return ""; // Serialization base case
            StringBuilder stringBuilder = new StringBuilder();
            stringBuilder.append(root.val).append(",").append(root.children.size()); // Add root val+,+num of children
            for (Node child : root.children)
                stringBuilder.append(",").append(serialize(child)); // Add children recursively, one by one
            return stringBuilder.toString(); // Return result
        }
    
        int i;
    
        public Node deserialize(String data) {
            if (data.isBlank()) return null; // Base case root is null
            i = 0; // The index on the tokens
            return recursiveDeserialize(data.split(",")); // Recursively build the tree from the tokenized string
        }
    
        private Node recursiveDeserialize(String[] nums) {
            if (i == nums.length) return null; // Base case- no more child
            Node root = new Node(Integer.parseInt(nums[i++]), new ArrayList<>()); // Build the root
            int childrenCount = Integer.parseInt(nums[i++]); // Get number of children
            for (int j = 0; j < childrenCount; j++) { // Add children recursively one by one
                Node child = recursiveDeserialize(nums);
                if (child != null) root.children.add(child); // If child is not null, add it to the children of root
            }
            return root; // Return the root of the tree
        }
    
    }