序列化二叉树

该博客讨论了如何实现二叉树的序列化和反序列化,允许使用不同的遍历方式和自定义序列化格式。重点在于先序遍历的序列化和反序列化实现,其中序列化时遇到空节点用'#'表示,反序列化时从字符串中解析并构建二叉树。
摘要由CSDN通过智能技术生成

题目描述

请实现两个函数,分别用来序列化和反序列化二叉树,不对序列化之后的字符串进行约束,但要求能够根据序列化之后的字符串重新构造出一棵与原二叉树相同的树。

二叉树的序列化是指:把一棵二叉树按照某种遍历方式的结果以某种格式保存为字符串,从而使得内存中建立起来的二叉树可以持久保存。序列化可以基于先序、中序、后序、层序的二叉树等遍历方式来进行修改,序列化的结果是一个字符串,序列化时通过 某种符号表示空节点(#),以 ! 表示一个结点值的结束(value!)。

二叉树的反序列化是指:根据某种遍历顺序得到的序列化字符串结果str,重构二叉树。

例如,可以根据层序遍历并特定标志空结点的方案序列化,也可以根据满二叉树结点位置的标号规律来序列化,还可以根据先序遍历和中序遍历的结果来序列化。

假如一棵树共有 2 个结点, 其根结点为 1 ,根结点右子结点为 2 ,没有其他结点。按照上面第一种说法可以序列化为“1,#,2,#,#”,按照上面第二种说法可以序列化为“{0:1,2:2}”,按照上面第三种说法可以序列化为“1,2;2,1”,这三种序列化的结果都包含足以构建一棵与原二叉树完全相同的二叉树的信息。

不对序列化之后的字符串进行约束,所以欢迎各种奇思妙想。

输入输出

输入:{8,6,10,5,7,9,11}
返回值:{8,6,10,5,7,9,11}

解题思路

题目的意思是,按照任意中遍历方式,序列化就是遇到节点为空的情况就在序列中存储‘#’。并且序列化中存储是用字符串形式;反序列化就是从序列化形式转换为二叉树的存储形式。
这里以先序遍历方式进行序列化和反序列化的实现。

  • 序列化
    序列化的函数中按照先序遍历方式存储每一个节点(存储的节点值要转换为字符串的形式),只不过需要判断节点为空的情况,当节点为空时,将‘#’存储到序列中,最后将所有值拼接起来;
  • 反序列化
    反序列化将序列化后的结果进行分割,判断边界条件:序列化列表为空的情况直接返回None;每次从序列化列表中取出第一个值并且从序列化列表中删除,将该值转换为整型后作为树的节点值创建为树的节点(注意,如果取出的值为‘#’,则返回None);递归调用函数完成左子树和右子树节点的创建,然后让根节点的左指针指向左节点,根节点的右指针指向右节点,这样就完成了树的创建。

代码示例

# coding:utf-8
class TreeNode:
    def __init__(self, x):
        self.val = x
        self.left = None
        self.right = None


class Solution:
    # 序列化——结果为字符串
    def Serialize(self, root):
        # 返回值列表,存储序列化的结果
        serializeList = []
        # 先序遍历函数
        def preOrder(root):
            # 如果遍历的节点为空,则向列表中加入'#'
            if root == None:
                serializeList.append('#')
                return serializeList
            # 不为空,则按照常规先序遍历递归的遍历节点,
            # 注意要讲节点的值以字符串的形式加入到序列化列表中
            serializeList.append(str(root.val))
            # 递归遍历左右子树
            preOrder(root.left)
            preOrder(root.right)
            return serializeList
        # 记得调用内部封装函数
        preOrder(root)
        # 要求序列化返回的是字符串,
        # 所以需要使用空格拼接,将列表中的值拼接成字符串返回
        return ' '.join(serializeList)

    # 反序列化——结果为常规树的遍历结果
    def Deserialize(self, s):
        # 考虑边界条件,传入的参数为空
        if s == []:
            return None
        # 不为空的情况,需要先将序列化的字符串结果划分,保存为列表
        deSerializeList = s.split()
        # 封装反序列的函数,递归使用
        def dePreOrder():
            # 每次将列表中第一的值取出并从列表中删除
            rootValue = deSerializeList.pop(0)
            # 如果取到的值时'#',则直接返回None
            if rootValue == '#':
                return None
            # 否则,将取出的值以整型的形式创建为树的节点
            node = TreeNode(int(rootValue))

            # 递归的完成左右节点转换
            leftNode = dePreOrder()
            rightNode = dePreOrder()
            # 连接节点的左右节点
            node.left = leftNode
            node.right = rightNode
            return node
        # 调用函数
        pRoot = dePreOrder()
        return pRoot



if __name__ == '__main__':
    # 8, 6, 6, 5, 7, 7, 5
    node1 = TreeNode(8)
    node2 = TreeNode(6)
    node3 = TreeNode(10)
    node4 = TreeNode(5)
    node5 = TreeNode(7)
    node6 = TreeNode(9)
    node7 = TreeNode(11)
    node1.left = node2
    node1.right = node3
    node2.left = node4
    node2.right = node5
    node3.left = node6
    node3.right = node7
    s = Solution()
    res = s.Serialize(node1)
    print(res)
    res2 = s.Deserialize(res)
    print(res2)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值