37. 序列化二叉树

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

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

剑指 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
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值