Serialization and deserialization binary tree ----- preorder, inorder, postorder, layer order

Table of contents

1. Serialization and deserialization

1. What is serialization and deserialization

2. Preorder traversal

1. Serialization

1. Problem analysis

2. Code implementation

2. Deserialization

1. Problem analysis

2. Code implementation

3. Post-order traversal

1. Serialization

1. Thinking Analysis

2. Code implementation

2. Deserialization

1. Thinking Analysis

2. Code implementation

Four. Inorder traversal

1. Serialization

1. Thinking Analysis

2. Code implementation

2. Deserialization

1. Thinking Analysis

5. Layer order traversal

1. Serialization

1. Thinking Analysis

2. Code implementation

2. Deserialization

1. Thinking Analysis

2. Code implementation


1. Serialization and deserialization

1. What is serialization and deserialization

Serialization (Serialization) is the process of converting objects into byte sequences to facilitate data transfer during network transmission and storage. During the serialization process, the state information of the object is converted into a format (such as byte array, XML, JSON, etc.) that can be stored or transmitted, so that it can be deserialized into the original object when needed. Serialization can be used to transfer objects between different systems, or store objects on disk, etc.

Deserialization is the process of restoring the serialized byte stream into an object, that is, restoring the original object state information. During the deserialization process, the byte stream can be converted into the original object according to the format used during serialization, so that the state of the original serialized object can be restored.

Serialization and deserialization can make it easier and more reliable to transfer or store object state information between different applications or systems.

Our serialization here is to convert the tree object into a string, and deserialization is to convert the string back into a tree object

2. Preorder traversal

1. Serialization

1. Problem analysis

We first convert the tree into a string according to the pre-order traversal. In fact, it is very simple. It is a pre-order traversal, plus the splicing operation of the string. Empty nodes are replaced by '#', and adjacent nodes are separated by ','

For example, the binary tree in the above figure, we serialize it into a string should be {2,1,#,6,#,#,3,#,#}

Our code is actually very easy to implement. This is actually the pre-order traversal, and the empty node is the post-splicing#.

If you don't understand preorder, inorder, postorder, and layer order traversal, I recommend reading the explanation in this article: tree traversal methods (front, middle, back, layer order traversal, recursion, iteration, Morris traversal)---- -Direct query code_Yun Xinchen's Blog-CSDN Blog

2. Code implementation

    //前序遍历序列化
    public String preOrderSerialize(TreeNode root) {
        StringBuilder sb = new StringBuilder();
        preOrderSerialize(root, sb);
        sb.deleteCharAt(sb.length() - 1);
        return sb.toString();

    }

    public void preOrderSerialize(TreeNode root, StringBuilder sb) {
        if (root == null) {
            sb.append("#" + ",");
            return;
        }
        sb.append(root.val + ",");
        preOrderSerialize(root.left, sb);
        preOrderSerialize(root.right, sb);

    }

2. Deserialization

1. Problem analysis

How do we deserialize this tree according to the string? In fact, the idea of ​​recursion is to refer to the pre-order traversal. For this string data, each node is separated by ",", and the first pre-order traversal Each element is the root node (the key is to find the root node of each subtree), so we traverse the string from front to back, so that the nodes are built layer by layer, and then recursively connected later, the entire binary tree The construction is successful, and it will be easier to understand why this recursion is performed by looking at the following figure

2. Code implementation

    //前序遍历反序列化
    public TreeNode preOrderDeserialize(String data) {
        String[] split = data.split(",");
        return preOrderDeserialize(split);

    }

    int index = 0;

    public TreeNode preOrderDeserialize(String[] nodes) {
        if (index >= nodes.length) {
            return null;
        }
        String node = nodes[index++];
        if (node.equals("#")) {
            return null;
        }
        //根
        TreeNode root = new TreeNode(Integer.parseInt(node));
        //左
        root.left = preOrderDeserialize(nodes);
        //右
        root.right = preOrderDeserialize(nodes);
        return root;

    }

3. Post-order traversal

1. Serialization

1. Thinking Analysis

Still this binary tree, according to the order of post-order traversal, it is easy to write code

The serialized string of this post-order traversal should be: {#,#,#,6,1,#,#,3,2};

2. Code implementation

    //后序遍历序列化
    public String postOrderSerialize(TreeNode root) {
        StringBuilder sb = new StringBuilder();
        postOrderSerialize(root, sb);
        sb.deleteCharAt(sb.length() - 1);
        return sb.toString();

    }

    public void postOrderSerialize(TreeNode root, StringBuilder sb) {
        if (root == null) {
            sb.append("#" + ",");
            return;
        }
        postOrderSerialize(root.left, sb);
        postOrderSerialize(root.right, sb);
        sb.append(root.val + ",");

    }

2. Deserialization

1. Thinking Analysis

The deserialization of the post-order traversal and the deserialization of the pre-order traversal are still somewhat different, but the general idea is the same, that is, to find the location of the root node, and then recursively build a binary tree step by step, according to the post-order traversal Features, we know that the root node of the tree is at the end of the string, and then move the index forward. At this time, can we copy the preorder traversal deserialization code? Of course not, we can according to the following figure It is clear that the front of the root node is the node of the right subtree, so we should build the right subtree first, and then build the left subtree.

2. Code implementation

    //后序遍历反序列化
    public TreeNode postOrderDeserialize(String data) {
        String[] split = data.split(",");
        index2 = split.length - 1;
        return postOrderDeserialize(split);

    }

    int index2;

    public TreeNode postOrderDeserialize(String[] nodes) {
        if (index2 < 0) {
            return null;
        }
        String node = nodes[index2--];
        if (node.equals("#")) {
            return null;
        }
        //根
        TreeNode root = new TreeNode(Integer.parseInt(node));
        //左
        root.right = postOrderDeserialize(nodes);
        //右
        root.left = postOrderDeserialize(nodes);
        return root;

    }

Four. Inorder traversal

1. Serialization

1. Thinking Analysis

The idea of ​​the above two questions is the same, according to the order of in-order traversal, complete the serialization of in-order traversal

Still above the tree, the serialized answer of in-order traversal should be: {#,1,#,6,#,2,#,3,#};

2. Code implementation

    //中序遍历序列化
    public String infixOrderSerialize(TreeNode root) {
        StringBuilder sb = new StringBuilder();
        infixOrderSerialize(root, sb);
        sb.deleteCharAt(sb.length() - 1);
        return sb.toString();

    }

    public void infixOrderSerialize(TreeNode root, StringBuilder sb) {
        if (root == null) {
            sb.append("#" + ",");
            return;
        }
        infixOrderSerialize(root.left, sb);
        sb.append(root.val + ",");
        infixOrderSerialize(root.right, sb);

    }

2. Deserialization

1. Thinking Analysis

In-order traversal cannot be deserialized. We can think about the reason here. In the deserialization of pre-order traversal and post-order traversal, our most important step is to find the root node, and the string in the in-order traversal , we cannot determine the location of the root node, so we cannot deserialize

5. Layer order traversal

1. Serialization

1. Thinking Analysis

Layer-order traversal is actually serialization with the help of queues, just like layer-order traversal, layer by layer, but when we encounter non-empty nodes, we need to add them to the queue, because when serializing, empty nodes default Converted to "#", if the element out of the queue is null, we add this element and continue the operation.

The serialization result of layer order traversal is: {2,1,3,#,6,#,#,#,#};

2. Code implementation

    public String levelOrderSerialize(TreeNode root) {
        StringBuilder sb = new StringBuilder();
        LinkedList<TreeNode> queue = new LinkedList<>();
        queue.offer(root);
        while (!queue.isEmpty()) {
            TreeNode pop = queue.pop();
            if (pop == null) {
                sb.append("#" + ",");
                continue;
            }
            sb.append(pop.val + ",");
            queue.offer(pop.left);
            queue.offer(pop.right);

        }
        sb.deleteCharAt(sb.length() - 1);        
        return sb.toString();

    }

2. Deserialization

1. Thinking Analysis

The idea of ​​deserialization is actually very similar to the idea of ​​serialization. Every time you find the root node, then put the left and right nodes into the queue, and proceed in turn.

2. Code implementation

    public TreeNode levelOrderDeserialize(String data) {
        String[] nodes = data.split(",");
        if (nodes[0].equals("#")) {
            return null;
        }
        int index = 1;
        TreeNode root = new TreeNode(Integer.parseInt(nodes[0]));
        LinkedList<TreeNode> queue = new LinkedList<>();
        queue.offer(root);
        while (!queue.isEmpty()) {
            TreeNode parent = queue.pop();
            if (nodes[index].equals("#")) {
                parent.left = null;
            } else {
                parent.left = new TreeNode(Integer.parseInt(nodes[index]));
                queue.offer(parent.left);
            }
            index++;
            if (nodes[index].equals("#")) {
                parent.right = null;
            } else {
                parent.right = new TreeNode(Integer.parseInt(nodes[index]));
                queue.offer(parent.right);

            }
            index++;
        }

        return root;
        
    }

Guess you like

Origin blog.csdn.net/qq_64580912/article/details/130089199