https://leetcode-cn.com/problems/serialize-and-deserialize-binary-tree/solution/shou-hui-tu-jie-gei-chu-dfshe-bfsliang-chong-jie-f/
抄的力扣一位大佬的
前序遍历解法 DFS
基本思想:
(1)序列化:
遍历将各个节点的值放到一个列表中
将列表用join()再变成字符串
(2)反序列化:
确定根节点root,然后遵循前序遍历的结果,递归生成左右子树
具体实现:
几个内置函数
(1)join()
str = "-"; seq = ("a", "b", "c"); # 字符串序列 print str.join( seq );
a-b-c
(2)next()
next(迭代器)
每执行一次,返回迭代器中的下一个项目
只有迭代器才能用next()
(3)iter()
将可迭代对象变成迭代器
https://www.liaoxuefeng.com/wiki/1016959663602400/1017323698112640
(4)split()
按规定字符将字符串分割开
string = "www.gziscas.com.cn" print(string.split('.')) ['www', 'gziscas', 'com', 'cn']
代码:
def serialize(self, root): """Encodes a tree to a single string. :type root: TreeNode :rtype: str """ def dfs(node): if node: vals.append(str(node.val)) dfs(node.left) dfs(node.right) else: vals.append("#") vals = [] dfs(root) return ",".join(vals) def deserialize(self, data): """Decodes your encoded data to tree. :type data: str :rtype: TreeNode """ def dfs(): v = next(vals) if v == "#": return None node = TreeNode(int(v)) node.left = dfs() node.right = dfs() return node vals = iter(data.split(",")) return dfs()
基本思想:
DFS
前序遍历
具体实现:
序列化:
递归三步:
1、递归参数以及返回结果
参数:根节点
返回结果:以这个节点为根节点的序列化·
2、递归终止条件
递归到null节点返回
3、单层递归逻辑
递归遍历一棵树,重点关注当前节点,他的自述的遍历交给递归完成
“serialize函数,请帮我分别序列化我的左右子树,我等你返回的结果,再拼接一下。”
反序列化:
递归三步:
1、确定递归参数以及返回值
递归参数:二叉树序列化后的字符串
返回值:当前构建好的root
2、递归终止条件
遍历到‘x’时,代表碰到了空节点,返回null
3、单层递归逻辑
定义函数 buildTree 用于还原二叉树,传入由序列化字符串转成的 list 数组。
逐个 pop 出 list 的首项,构建当前子树的根节点,顺着 list,构建顺序是根节点,左子树,右子树。
如果弹出的字符为 "X",则返回 null 节点。
如果弹出的字符是数值,则创建root节点,并递归构建root的左右子树,最后返回root。
代码:
public class Codec { // Encodes a tree to a single string. public String serialize(TreeNode root) { if (root == null) return "X,"; String leftSerialize = serialize(root.left); //左子树的序列化字符串 String rightSerialize = serialize(root.right); //右子树的序列化字符串 return root.val + "," + leftSerialize + rightSerialize;//能递归到的节点都当过根节点 } /* public String serialize(TreeNode root) { if (root == null) return "X"; String leftSerialize = serialize(root.left); //左子树的序列化字符串 String rightSerialize = serialize(root.right); //右子树的序列化字符串 return root.val + "," + leftSerialize +","+ rightSerialize; } */ // Decodes your encoded data to tree. public TreeNode deserialize(String data) { String[] temp = data.split(","); Deque<String> dp = new LinkedList<>(Arrays.asList(temp)); return buildTree(dp); } private TreeNode buildTree(Deque<String> dq){ String s = dq.poll(); //返回当前结点 if (s.equals("X")) return null; TreeNode node = new TreeNode(Integer.parseInt(s)); node.left = buildTree(dq); //构建左子树 node.right = buildTree(dq); //构建右子树 return node; } }
层级遍历解法 BFS
基本思想:
先捋清楚啥是层级遍历就啥也好说了
具体实现:
序列化
和DFS得到的不同,它是一层层的。除了第一个是根节点的值,其他节点值都是成对的,对应左右子节点。
反序列化
依然先转成list数组,用一个指针 cursor 从第二项开始扫描。
起初,用list[0]构建根节点,并让根节点入列。
节点出列,此时 cursor 指向它的左子节点值,cursor+1 指向它的右子节点值。
如果子节点值是数值,则创建节点,并认出列的父亲,同时自己也是父亲,入列。
如果子节点值为 'X',什么都不用做,因为出列的父亲的 left 和 right 本来就是 null
可见,所有的真实节点都会在队列里走一遍,出列就带出儿子入列
代码:
public class Codec { // Encodes a tree to a single string. public String serialize(TreeNode root) { if (root == null) { return ""; } StringBuilder sb = new StringBuilder();//创建一个放结果的字符串 Queue<TreeNode> queue = new LinkedList<>();//创建一个队列 queue.offer(root);//放入待考察的节点 while (!queue.isEmpty()) { TreeNode node = queue.poll(); //考察出列的节点 if (node == null) {//不是真实节点 sb.append("X,"); } else {//是真实节点 sb.append(node.val + ","); //节点值加入sb queue.offer(node.left);//子节点入列,不管是不是null节点都入列 queue.offer(node.right); } } return sb.toString(); } // Decodes your encoded data to tree. public TreeNode deserialize(String data) { if (data == "") { return null; } //序列化字符串给转为成数组 Queue<String> nodes = new ArrayDeque<>(Arrays.asList(data.split(","))); //获取首项,构建根节点 TreeNode root = new TreeNode(Integer.parseInt(nodes.poll())); //创建一个队列 Queue<TreeNode> queue = new ArrayDeque<>(); //根节点推入队列 queue.offer(root); while (!queue.isEmpty()) { TreeNode node = queue.poll(); //考察出列的节点 String left = nodes.poll(); // 左儿子 String right = nodes.poll(); // 右儿子 if (!left.equals("X")) { // 是真实节点 node.left = new TreeNode(Integer.parseInt(left)); // 创建左儿子节点,然后认父亲 queue.add(node.left); //左儿子自己也是父亲,入列 } if (!right.equals("X")) { node.right = new TreeNode(Integer.parseInt(right)); queue.add(node.right); } } return root; } }