37. 序列化二叉树

本文介绍了如何实现二叉树的序列化和反序列化,使用层序遍历方法,将二叉树转化为字符串,再将字符串还原为二叉树。Java代码示例展示了具体实现过程。

剑指 Offer 37. 序列化二叉树

297.二叉树的序列化与反序列化

请实现两个函数,分别用来序列化和反序列化二叉树。

示例:

你可以将以下二叉树:

    1
   / \
  2   3
     / \
    4   5

序列化为 "[1,2,3,null,null,4,5]"

注意:本题与主站 297 题相同:https://leetcode-cn.com/problems/serialize-and-deserialize-binary-tree/

解题思路

做过一定数量二叉树题目的同学一定会发现,题目如果用数组形式表示一颗二叉树时,都是用层序遍历表示的,并且null也会给出,因为这样才好唯一确定一棵树。因此这里序列化我们也用层序遍历,为完整表示二叉树,考虑将叶节点下的 null 也记录。在此基础上,对于列表中任意某节点 node ,其左子节点 node.left 和右子节点 node.right 在序列中的位置便是唯一确定的了。

Java代码

/**
 * 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) {
        StringBuilder sb = new StringBuilder();
        Queue<TreeNode> queue = new LinkedList<>();
        if(root == null) return "null";
		
		//层序遍历,用“,”隔开每个元素,最后会多出一个“,”但是没什么关系。
       //因为反序列化时,用‘,’切分,自然就去掉最后的‘,’了
        queue.add(root);
        sb.append(root.val).append(",");
        while(!queue.isEmpty()){
            TreeNode cur = queue.poll();
            if(cur.left != null){
                queue.add(cur.left);
                sb.append(cur.left.val).append(",");
            }else{
                sb.append("null,");
            }
            if(cur.right != null){
                queue.add(cur.right);
                sb.append(cur.right.val).append(",");
            }else{
                sb.append("null,");
            }
        }
        //System.out.print(sb.toString());用于查看是否序列化成功
        return sb.toString();
    }

    // Decodes your encoded data to tree.
    public TreeNode deserialize(String data) {
        String[] strs = data.split(",");
        
        if(strs.length == 0 || strs[0].equals("null")) return null;

        TreeNode root = new TreeNode(Integer.valueOf(strs[0]));
        Queue<TreeNode> queue = new LinkedList<>();
        queue.add(root);
        int index = 1;
        while(index < strs.length){
            TreeNode node = queue.poll();
            if (node != null) {//按照层序遍历特性,当前节点不是null的话,就从数组中读取两个值作为其左右子节点
                TreeNode left = strs[index].equals("null") ? null : new TreeNode(Integer.valueOf(strs[index]));
                index++;
                queue.add(left);
                node.left = left;

                TreeNode right = strs[index].equals("null") ? null : new TreeNode(Integer.valueOf(strs[index]));
                index++;
                queue.add(right);
                node.right = right;
            }
        }
        return root;
    }
}

// Your Codec object will be instantiated and called as such:
// Codec codec = new Codec();
// codec.deserialize(codec.serialize(root));

在这里插入图片描述

Go代码

/**
 * Definition for a binary tree node.
 * type TreeNode struct {
 *     Val int
 *     Left *TreeNode
 *     Right *TreeNode
 * }
 */

type Codec struct {
    
}

func Constructor() Codec {
    return Codec{}
}

// Serializes a tree to a single string.
func (this *Codec) serialize(root *TreeNode) string {
    if root == nil {
        return "null"
    }
    // 层序遍历,用,连接手游节点的字符串表示
    sb := strings.Builder{}
    queue := make([]*TreeNode,0)
    queue = append(queue,root)
    sb.WriteString(fmt.Sprintf("%d,",root.Val))
    for len(queue) != 0 {
        curNode := queue[0]
        queue = queue[1:]
        if curNode.Left != nil {
            sb.WriteString(fmt.Sprintf("%d,",curNode.Left.Val))
            queue = append(queue,curNode.Left)
        } else {
            sb.WriteString("null,")
        }
        
        if curNode.Right != nil {
            sb.WriteString(fmt.Sprintf("%d,",curNode.Right.Val))
            queue = append(queue,curNode.Right)
        } else {
            sb.WriteString("null,")
        }
    }
    res := sb.String()
    // 去除最后的逗号返回
    return res[0:len(res) - 1]
}

// Deserializes your encoded data to tree.
func (this *Codec) deserialize(data string) *TreeNode {  
    // 将数据按,号分割后,再按层序变成树
    dataArr := strings.Split(data,",")
    if len(dataArr) == 0 || dataArr[0] == "null" {
        return nil
    }
    rootVal ,_:= strconv.Atoi(dataArr[0])
    root := &TreeNode{Val:rootVal}
    queue := make([]*TreeNode,0)
    queue = append(queue,root)
    index := 1
    for index < len(dataArr) {
        curNode := queue[0]
        queue = queue[1:]
        if curNode != nil {
            left,right := &TreeNode{},&TreeNode{}
            if dataArr[index] == "null" {
                left = nil
            } else {
                leftVal ,_:= strconv.Atoi(dataArr[index])
                left = &TreeNode{Val:leftVal}
            }
            curNode.Left = left
            queue = append(queue,left)
            index++

            if dataArr[index] == "null" {
                right = nil
            } else {
                rightVal ,_:= strconv.Atoi(dataArr[index])
                right = &TreeNode{Val:rightVal}
            }
            curNode.Right = right
            queue = append(queue,right)
            index++
        }

    }
    return root
}


/**
 * Your Codec object will be instantiated and called as such:
 * ser := Constructor();
 * deser := Constructor();
 * data := ser.serialize(root);
 * ans := deser.deserialize(data);
 */
树的存储与遍历: 1.初始化二叉树 ```c++ #include <iostream> using namespace std; struct TreeNode { int val; TreeNode* left; TreeNode* right; TreeNode(int x) : val(x), left(NULL), right(NULL) {} }; TreeNode* createTree() { int val; cin >> val; if (val == -1) { return NULL; } TreeNode* root = new TreeNode(val); root->left = createTree(); root->right = createTree(); return root; } ``` 2.先序遍历二叉树 ```c++ void preOrder(TreeNode* root) { if (root == NULL) { return; } cout << root->val << " "; preOrder(root->left); preOrder(root->right); } ``` 3.中序遍历二叉树 ```c++ void inOrder(TreeNode* root) { if (root == NULL) { return; } inOrder(root->left); cout << root->val << " "; inOrder(root->right); } ``` 4.后序遍历二叉树 ```c++ void postOrder(TreeNode* root) { if (root == NULL) { return; } postOrder(root->left); postOrder(root->right); cout << root->val << " "; } ``` 5.销毁二叉树 ```c++ void destroyTree(TreeNode* root) { if (root == NULL) { return; } destroyTree(root->left); destroyTree(root->right); delete root; } ``` 二叉树的复原: 1.由前序、中序序列确定复原二叉树 ```c++ TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) { if (preorder.empty() || inorder.empty()) { return NULL; } int rootVal = preorder[0]; TreeNode* root = new TreeNode(rootVal); vector<int>::iterator it = find(inorder.begin(), inorder.end(), rootVal); int leftSize = it - inorder.begin(); vector<int> leftPreorder(preorder.begin() + 1, preorder.begin() + 1 + leftSize); vector<int> leftInorder(inorder.begin(), it); vector<int> rightPreorder(preorder.begin() + 1 + leftSize, preorder.end()); vector<int> rightInorder(it + 1, inorder.end()); root->left = buildTree(leftPreorder, leftInorder); root->right = buildTree(rightPreorder, rightInorder); return root; } ``` 2.由中序、后序序列确定复原二叉树 ```c++ TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) { if (inorder.empty() || postorder.empty()) { return NULL; } int rootVal = postorder.back(); TreeNode* root = new TreeNode(rootVal); vector<int>::iterator it = find(inorder.begin(), inorder.end(), rootVal); int leftSize = it - inorder.begin(); vector<int> leftInorder(inorder.begin(), it); vector<int> leftPostorder(postorder.begin(), postorder.begin() + leftSize); vector<int> rightInorder(it + 1, inorder.end()); vector<int> rightPostorder(postorder.begin() + leftSize, postorder.end() - 1); root->left = buildTree(leftInorder, leftPostorder); root->right = buildTree(rightInorder, rightPostorder); return root; } ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值