二叉树的序列化(serialization)与反序列化(de-serialization)

这篇具有很好参考价值的文章主要介绍了二叉树的序列化(serialization)与反序列化(de-serialization)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

1. 概要

2. 二叉树的序列化

2.1 基于前序遍历的序列化

2.2 基于后序遍历的序列化

2.3 基于层序遍历的序列化

3. python实现

3.1 二叉树节点的表示

3.2 层序遍历序列化的python实现

3.3 层序遍历反序列化的python实现

3.4 测试 


1. 概要

        本文简要介绍二叉树的序列化处理和反序列化处理及对应的python实现。

        二叉树通常为了方便而以一维数组(比如说python list)的格式进行存储,二叉树的序列化(serialization)就是指将二叉树转换成列表或者一维数组的形式(或者说线性化表示)。实际使用的时候再由列表的形式变换回二叉树的格式,这个就是反序列化(de-serialization)。

        当然,更彻底的序列化和反序列化:Serialization is translating a data structure or object into a sequence of bits so that it can be stored in a file or memory buffer, or transmitted across a network. In the future, we can deserialize the sequence to reconstruct the same data structure or object. 即将一个数据结构或者对象转换为字节或甚至比特流,以方便存储和传输,并且要能够在需要使用的时候进行恢复。但是,由于转换为一维数组表示是进一步转换为字节流或这比特流的前提和必经之路,也是序列化的最关键的步骤,本文只讨论序列化到一维数组以及对饮的反序列化处理。

        序列化和反序列化是各种复杂的数据结构的实际存储和使用时都需要碰到的问题。

2. 二叉树的序列化

        二叉树的序列化的基本处理就是二叉树的层序遍历,而二叉树的遍历常用方法有以下几种:前序遍历,中序遍历,后序遍历,层序遍历。除了中序遍历外,其余三种遍历方法都可以实现二叉树的序列化,即得到二叉树的一维数组表示。

        虽然遍历是序列化处理的底层处理,但是,序列化又不仅仅是遍历。一个常见的误解是将二叉树进行遍历展开就得到了二叉树的一维数组表示。其实不是,单纯地对二叉树进行得到的列表无法还原成原始的二叉树。

二叉树的序列化(serialization)与反序列化(de-serialization)

        上图这个不完全的二叉树直接进行层序遍历得到的是[1,2,-3,-5,4],实际上它的一维数组表示为[1,2,-3,-5,null,4,null]。

        

        只有完全二叉树的常规遍历能够得到其序列化表示。所以,对于一般的(不完全)二叉树,其序列化处理可以考虑先将其补全为完全二叉树,不存在的节点用Null或None填充,然后再对该完全二叉树进行遍历即可。但是实际实现时不会去先执行Null或None填充,而是一边遍历一边执行Null或None填充。如下图所示:

二叉树的序列化(serialization)与反序列化(de-serialization)

         前序遍历和后序遍历和层序遍历都可以实现序列化,只要序列化和反序列化对称。但是中序遍历不适合于序列化实现。

        We cannot use the in-order tree traversal method to serialize and deserialize a binary tree. In an in-order binary tree traversal, we traverse the left subtree first. Then, we visit the root node and traverse the right subtree. This traversal makes it hard to locate the root node in the serialized sequence. For example, an in-order traversal of the following binary tree can produce a sequence: #,2,#,1,#: 

二叉树的序列化(serialization)与反序列化(de-serialization)

         However, we can produce the same in-order sequence on the following binary tree:

二叉树的序列化(serialization)与反序列化(de-serialization)

        也就是说,基于中序遍历可能存在不同的二叉树得到相同的序列化表示,这样就使得反序列化无法唯一地恢复原二叉树。因此,中序遍历不适合于序列化实现。 

2.1 基于前序遍历的序列化

        如下所示为一个递归方式实现的前序遍历序列化处理。

二叉树的序列化(serialization)与反序列化(de-serialization)

In this algorithm, we first serialize the root node data, then recursively serialize its left and right children. If we meet a  null node, we also serialize it with a special character #. 

        该算法的时间复杂度为O(n),因为每个节点只访问一次。空间复杂度(平均意义上来说)也是O(n),就是存储输出序列。注意,对于深度为k的完全二叉树,总共有个节点。最极端情况下,k个节点排成k层不完全二叉树,而且每一层的节点都是上一层的右子节点,那么在基于前序遍历的序列化处理后,需要 长度为的数组表示。

        与此对应的反序列化算法流程如下所示:

二叉树的序列化(serialization)与反序列化(de-serialization)

         前序遍历的顺序是先处理根节点,然后是左子树,最后是右子树。反序列化时则是相反的顺序,即先处理右子树,然后是左子树,最后是根节点。 

2.2 基于后序遍历的序列化

         同理可以得到基于后序遍历的序列化和反序列化算法流程如下所示:

二叉树的序列化(serialization)与反序列化(de-serialization)

二叉树的序列化(serialization)与反序列化(de-serialization)

         后序遍历的顺序是先处理左子树,然后是右子树,最后是根节点。反序列化时则是相反的顺序,即先处理根节点,然后是右子树,最后是左子树。

2.3 基于层序遍历的序列化

        基于层序遍历得到的二叉树的一维数组表示的基本规则是(为了方便,记该数组为a,0-indexing,并且采用python slicing的方式表示子数组):

        (1) a[0]表示根节点

        (2) a[2**k-1 : 2**(k+1)-1]表示层k(1,2,...)的节点(假定根节点位于层0)

        (3) 每一层中的节点按从左到右排列

        (4) 不存在(作为完全二叉树应该有但是实际上不存在)的节点用None或者Null填充

        (5) 最后的连续的None可以去除 

 

3. python实现

3.1 二叉树节点的表示

class TreeNode:
    def __init__(self, val=0, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right

        每个二叉树的节点最都有两个子节点,分别为左子节点和右子节点。以上类定义中,分别用left和right指向左子节点和右子节点。

3.2 层序遍历序列化的python实现

         实现思路:to be added

def binTree2Lst(root):
    """ 
    binary tree serialization.
    Convert a binary tree with "root" as its root to a list.
    """
    if root == None:
        return []

    nodeLst = [root]
    valLst  = []
    
    while len(nodeLst) > 0:
        curNode = nodeLst.pop()
        if curNode != None:
            nodeLst.insert(0,curNode.left)
            nodeLst.insert(0,curNode.right)        
            valLst.append(curNode.val)
        else:
            valLst.append(None)

    # Throw away the trailing 'None'
    while valLst[-1] == None:
        valLst.pop()

    return valLst

3.3 层序遍历反序列化的python实现

        实现思路:to be added

def lst2bintree(x:List[int]) -> Optional[TreeNode]:
    if len(x) == 0: # []
        root = None
    if x[0] == None: # [None]
        root = None

    x.reverse() # For the convenience of utilizing x.pop()
    nodeLoL = []        
    root = TreeNode(x.pop())
    nodeLoL.append([root])
    k = 0
    while(1):
        #print('k = {0}, {1}'.format(k, x))
        newLayer = []
        for node in nodeLoL[k]:
            #print(node.val)
            if node == None:
                pass
            else:
                if len(x) == 0:
                    break
                tmp = x.pop()
                if tmp != None:
                    newNode = TreeNode(tmp)
                    node.left = newNode
                    newLayer.append(newNode)

                if len(x) == 0:
                    break
                tmp = x.pop()
                if tmp != None:
                    newNode = TreeNode(tmp)
                    node.right = newNode
                    newLayer.append(newNode)

        if len(x) == 0:
            break
        nodeLoL.append(newLayer)
        k += 1
        
    return root

3.4 测试 

    x   = [3,9,20,None,None,15,7]
    root = lst2bintree(x)
    print(root.val)
    print(root.left.val)
    print(root.right.val)
    print(root.left.left)
    print(root.left.right)    
    print(root.right.left.val)
    print(root.right.right.val)  
    print(binTree2Lst(root))

    x = [1,2,-3,-5,None,4,None]
    root = lst2bintree(x)
    print(binTree2Lst(root))

        运行结果如下: 

3
9
20
None
None
15
7
[3, 9, 20, None, None, 15, 7] 

[1, 2, -3, -5, None, 4]文章来源地址https://www.toymoban.com/news/detail-456282.html

到了这里,关于二叉树的序列化(serialization)与反序列化(de-serialization)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 想要精通算法和SQL的成长之路 - 二叉树的序列化和反序列化问题

    想要精通算法和SQL的成长之路 - 系列导航 二叉树的层序遍历 像这种从上至下并且按层打印的,可以称之为 二叉树的广度优先搜索( BFS ) 。而这类算法往往借助 队列的一个先入先出特性 来实现。 那么有这么几个步骤: 1.特殊处理还有初始化动作。 2. BFS 循环: 最终完整代

    2024年02月07日
    浏览(37)
  • 刷题日记01:序列化和反序列化二叉树

    一.概念理解: 题目如下:https://leetcode.cn/problems/xu-lie-hua-er-cha-shu-lcof/ 何为序列化? 序列化我们可以理解为层序遍历的结果,即将所有的结点的信息,按照层序遍历的结果拼接到一个字符串中,但是与一般的层序遍历有所不同的是:序列化要输出所有的结点信息,而层序遍历

    2024年02月13日
    浏览(46)
  • 【序列化与反序列化】关于序列化与反序列化MessagePack的实践

    在进行序列化操作之前,我们还对系统进行压测,通过 jvisualvm 分析cpu,线程,垃圾回收情况等;运用火焰图 async-profiler 分析系统性能,找出程序中占用CPU资源时间最长的代码块。 代码放置GitHub:https://github.com/nateshao/leetcode/tree/main/source-code/src/main/java/com/nateshao/source/code/ser

    2024年02月11日
    浏览(47)
  • 【Linux】序列化与反序列化

    目录 前言 什么是应用层? 再谈\\\"协议\\\"  什么是序列化和反序列化 网络版计算器 整体流程实现 Sock.hpp的实现 TcpServer.hpp的实现 Protocol.hpp的实现 CalServer.cc的编写 CalClient.cc的编写 整体代码           本章是属于TCP/UDP四层模型中的第一层 应用层 相关的内容。主要介绍了序列

    2024年02月10日
    浏览(33)
  • 序列化与反序列化读取配置文件

    定义一个连接配置文件类OmCipNetParam 定义一个结构体,传递函数运行结果和运行信息 ​ 使用Newtonsoft.Json进行序列化和反序列化读写配置文件 同理反序列读取配置文件 注意这里需要引入库

    2024年02月08日
    浏览(44)
  • 4.4. 对象序列化与反序列化

    在本节中,我们将详细讨论Java中的对象序列化与反序列化概念、使用方法以及实例。对象序列化是将对象的状态信息转换为字节流的过程,而反序列化则相反,是将字节流恢复为对象的过程。 4.4.1 为什么需要对象序列化? 对象序列化的主要目的是为了在不同的系统间传输对

    2024年02月07日
    浏览(42)
  • Flutter笔记:序列化与反序列化

    Flutter笔记 序列化与反序列化 作者 : 李俊才 (jcLee95):https://blog.csdn.net/qq_28550263 邮箱 : 291148484@163.com 本文地址 :https://blog.csdn.net/qq_28550263/article/details/133340592 序列化是一种将复杂数据结构(例如对象、数组、字典等)转换为线性格式或字节流的过程,以便于数据的存储

    2024年02月07日
    浏览(41)
  • 【计算机网络】序列化与反序列化

    通过打包的方式,将结构体message发送给对方 对方收到后就会报告给上层QQ客户端 结构化的数据 是由 多个 string 构成的 而以前在网络套接字 发送时,都是按照一个字符串的方式来发送和接收的 所以想办法 ,把多个字符串 转化为 一个大\\\"字符串\\\",对方在接收时也是一个长的

    2024年02月10日
    浏览(35)
  • Springboot Jackson 序列化与反序列化配置

    可解决在使用默认反序列化Jackson时,LocalDateTime类型的请求参数反序列化失败的问题

    2024年02月02日
    浏览(35)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包