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

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

前言

想要精通算法和SQL的成长之路 - 系列导航

一. 二叉树的层序遍历(BFS)

二叉树的层序遍历
想要精通算法和SQL的成长之路 - 二叉树的序列化和反序列化问题,精通算法和SQL之路,算法,sql,linux
像这种从上至下并且按层打印的,可以称之为二叉树的广度优先搜索(BFS。而这类算法往往借助队列的一个先入先出特性来实现。

那么有这么几个步骤:
1.特殊处理还有初始化动作。

List<List<Integer>> res = new ArrayList<>();
// 树为空,返回空数组
if (root == null) {
    return res;
}
// 初始化队列
LinkedList<TreeNode> queue = new LinkedList<>();
queue.add(root);

2.BFS循环:

while (!queue.isEmpty()) {
    // 该层的打印结果
    ArrayList<Integer> tmp = new ArrayList<>();
    // 将当前层(队列内的元素)全部打印
    for (int i = queue.size(); i > 0; i--) {
        // 队首先出
        TreeNode node = queue.poll();
        tmp.add(node.val);
        // 从左往右添加元素(先进先出)
        if (node.left != null) {
            tmp.add(node.left.val);
        }
        if (node.right != null) {
            tmp.add(node.right.val);
        }
    }
    // 当前层的遍历结果加入到最终结果集中
    res.add(tmp);
}

最终完整代码如下:

public List<List<Integer>> levelOrder(TreeNode root) {
    List<List<Integer>> res = new ArrayList<>();
    // 树为空,返回空数组
    if (root == null) {
        return res;
    }
    // 初始化队列
    LinkedList<TreeNode> queue = new LinkedList<>();
    queue.add(root);
    while (!queue.isEmpty()) {
        // 该层的打印结果
        ArrayList<Integer> tmp = new ArrayList<>();
        // 将当前层(队列内的元素)全部打印
        for (int i = queue.size(); i > 0; i--) {
            // 队首先出
            TreeNode node = queue.poll();
            tmp.add(node.val);
            // 从左往右添加元素(先进先出)
            if (node.left != null) {
                tmp.add(node.left.val);
            }
            if (node.right != null) {
                tmp.add(node.right.val);
            }
        }
        // 当前层的遍历结果加入到最终结果集中
        res.add(tmp);
    }
    return res;
}

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

原题链接
想要精通算法和SQL的成长之路 - 二叉树的序列化和反序列化问题,精通算法和SQL之路,算法,sql,linux
从题目来看,序列化的操作就是:从上往下,从左往右的一个层级遍历。那么在做这个题目之前,我们可以看下这个题目:

那么我们回归本题,本题和1.1小节的题目有啥不同?

  • 如果是空节点,我们要输出null
  • 我们还要根据序列化的结果,反序列化回一颗二叉树。

我们依旧可以使用队列来解决。

2.1 序列化操作

首先,特判以及队列的初始化操作:

if (root == null) {
    return "[]";
}
StringBuilder res = new StringBuilder("[");
LinkedList<TreeNode> queue = new LinkedList<>();
queue.add(root);

顺带提一嘴,希望大家养成良好的编码习惯,关于字符串的equal比较,常量放在前面,变量放后面,避免不必要的空指针。

BFS递归操作:

while (!queue.isEmpty()) {
    // 队列先进先出,从队首开始出队
    for (int i = queue.size(); i > 0; i--) {
        TreeNode node = queue.poll();
        // 只不过这里多加了一个判断而已,如果是空节点,我们添加null
        if (node == null) {
            res.append("null,");
            continue;
        }
        // 否则,非空,添加当前节点的值
        res.append(node.val + ",");
        // 由于上面已经加了null的判断了,这里直接按顺序先加左节点,再加右节点即可。
        queue.add(node.left);
        queue.add(node.right);
    }
}

最后就是收尾工作:我们对于结尾的值,要把多余的逗号去除。

// 删除最后一个多余的逗号
res.deleteCharAt(res.length() - 1);
res.append("]");
return res.toString();

最终完整代码如下:

public String serialize(TreeNode root) {
    if (root == null) {
        return "[]";
    }
    StringBuilder res = new StringBuilder("[");
    LinkedList<TreeNode> queue = new LinkedList<>();
    queue.add(root);
    while (!queue.isEmpty()) {
        // 队列先进先出,从队首开始出队
        for (int i = queue.size(); i > 0; i--) {
            TreeNode node = queue.poll();
            // 只不过这里多加了一个判断而已,如果是空节点,我们添加null
            if (node == null) {
                res.append("null,");
                continue;
            }
            // 否则,非空,添加当前节点的值
            res.append(node.val + ",");
            // 由于上面已经加了null的判断了,这里直接按顺序先加左节点,再加右节点即可。
            queue.add(node.left);
            queue.add(node.right);
        }
    }
    // 删除最后一个多余的逗号
    res.deleteCharAt(res.length() - 1);
    res.append("]");
    return res.toString();
}

2.2 反序列化操作

同样地,特判以及队列的初始化操作:

if ("[]".equals(data)) {
    return null;
}
// 各个节点的值
String[] vals = data.substring(1, data.length() - 1).split(",");
// 第一个值必定是根节点(从上往下的特性)
TreeNode root = new TreeNode(Integer.parseInt(vals[0]));
LinkedList<TreeNode> queue = new LinkedList<TreeNode>() {{
    add(root);
}};

BFS操作:

int index = 1;
while (!queue.isEmpty()) {
    TreeNode node = queue.poll();
    // 处理左节点
    if (!"null".equals(vals[index])) {
        node.left = new TreeNode(Integer.parseInt(vals[index]));
        queue.add(node.left);
    }
    // 这里不管怎样都是要往后移动一位,如果是null,我们node.left就默认是null了。
    index++;
    if (!"null".equals(vals[index])) {
        node.right = new TreeNode(Integer.parseInt(vals[index]));
        queue.add(node.right);
    }
    index++;
}

完整代码:文章来源地址https://www.toymoban.com/news/detail-729060.html

public TreeNode deserialize(String data) {
    if ("[]".equals(data)) {
        return null;
    }
    String[] vals = data.substring(1, data.length() - 1).split(",");
    TreeNode root = new TreeNode(Integer.parseInt(vals[0]));
    LinkedList<TreeNode> queue = new LinkedList<TreeNode>() {{
        add(root);
    }};
    int index = 1;
    while (!queue.isEmpty()) {
        TreeNode node = queue.poll();
        // 处理左节点
        if (!"null".equals(vals[index])) {
            node.left = new TreeNode(Integer.parseInt(vals[index]));
            queue.add(node.left);
        }
        // 这里不管怎样都是要往后移动一位,如果是null,我们node.left就默认是null了。
        index++;
        if (!"null".equals(vals[index])) {
            node.right = new TreeNode(Integer.parseInt(vals[index]));
            queue.add(node.right);
        }
        index++;
    }
    return root;
}

到了这里,关于想要精通算法和SQL的成长之路 - 二叉树的序列化和反序列化问题的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

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

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

相关文章

  • 想要精通算法和SQL的成长之路 - 滑动窗口和大小根堆

    想要精通算法和SQL的成长之路 - 系列导航 先来说下大小根堆是什么: 大根堆:栈顶元素最大(上图左侧部分),栈底至栈顶元素值递增。 小根堆:栈顶元素最小(上图右侧部分),栈底至栈顶元素值递减。 在 Java 当中,可以用什么来表示大小根堆? 小根堆: 大根堆: 大小

    2024年02月07日
    浏览(30)
  • 想要精通算法和SQL的成长之路 - 分割数组的最大值

    想要精通算法和SQL的成长之路 - 系列导航 原题链接 首先面对这个题目,我们可以捕获几个: 非负整数。 非空连续子数组。 那么我们假设分割后的子数组,和的最大值是 M ,对应分割的子数组个数为 N 。他们之间必然存在以下关系: 分割的子数组个数 N 越多,对应的

    2024年02月07日
    浏览(30)
  • [C]二叉树的实现——喵喵成长记

    宝子,你不点个赞吗?不评个论吗?不收个藏吗? 最后的最后,关注我,关注我,关注我,你会看到更多有趣的博客哦!!! 喵喵喵,你对我真的很重要。 目录 前言 二叉树的定义 特殊的二叉树 二叉树的性质(超级重要) 代码实现 二叉树的练习题 总结 二叉树用C语言实现

    2024年02月04日
    浏览(23)
  • 算法D14 | 二叉树1 | 144. 二叉树的前序遍历 145. 二叉树的后序遍历 94. 二叉树的中序遍历

    理论基础  需要了解 二叉树的种类,存储方式,遍历方式 以及二叉树的定义  文章讲解: 二叉树既可以链式存储(利用指针,类似栈和队列),也可以用数组表示。 深度优先遍历 前序遍历(递归法,迭代法) 中序遍历(递归法,迭代法) 后序遍历(递归法,迭代法)

    2024年02月20日
    浏览(29)
  • 算法刷题Day 16 二叉树的最大深度+N叉树的最大深度+二叉树的最小深度+完全二叉树的节点个数

    递归法 迭代法 使用层序的方法,相对比较好理解 递归法 迭代法 跟二叉树的迭代差不多意思。 要想到是后序遍历 递归法 先计算左右两棵子树的节点数,再加和,用后序遍历的方法 迭代法 迭代法用层序遍历来处理 适用于完全二叉树的优化 完全二叉树优化方法没自己想出来

    2024年02月17日
    浏览(27)
  • 【算法第十四天7.28】二叉树的最大深度,二叉树的最小深度 ,完全二叉树的节点个数

    链接 力扣104-二叉树的最大深度 思路 链接 力扣111-二叉树的最小深度 思路 链接 力扣222-完全二叉树的节点个数 思路

    2024年02月14日
    浏览(26)
  • LeetCode算法二叉树—222. 完全二叉树的节点个数

    目录 222. 完全二叉树的节点个数 - 力扣(LeetCode) 代码: 运行结果:  给你一棵  完全二叉树  的根节点  root  ,求出该树的节点个数。 完全二叉树 的定义如下:在完全二叉树中,除了最底层节点可能没填满外,其余每层节点数都达到最大值,并且最下面一层的节点都集

    2024年02月07日
    浏览(31)
  • 数据结构和算法学习记录——平衡二叉树(基本介绍、平衡因子、平衡二叉树的定义、平衡二叉树的高度)

    目录 基本介绍 平衡因子 平衡二叉树  平衡二叉树的高度  什么是平衡二叉树? 以一个例子来解释一下: 搜索树结点按不同的插入次序,将会导致不同的深度和平均查找长度ASL   在二叉搜索树中查找一个元素:  (a)要找到Jan,需要查找一次;要找到Feb,需要查找两次;

    2023年04月26日
    浏览(45)
  • 二叉树的非递归遍历算法

    二叉树的遍历是指访问二叉树的每个结点,且每个结点仅被访问一次。二叉树的遍历可按二叉树的构成以及访问结点的顺序分为4种方式:先序遍历、中序遍历、后序遍历和层次遍历。请至少给出其中一种遍历方式的非递归算法的思路和代码,并举例演示算法的执行过程。 算

    2023年04月24日
    浏览(28)
  • 算法刷题Day 15 二叉树的层序遍历+翻转二叉树+对称二叉树

    层序遍历二叉树需要借助到队列 递归方法 迭代方法 就是简单的用上前序遍历迭代方法实现,不用想的太复杂 递归方法 迭代方法 这里使用了队列来存放两个要比较的结点。也可以使用栈,方法是类似的。

    2024年02月12日
    浏览(27)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包