[关闭]
@Catyee 2021-05-30T16:10:33.000000Z 字数 2746 阅读 523

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

数据结构与算法


leetcode 297 二叉树的序列化与反序列化

序列化是容易的,序列化的关键在于空节点的处理,空节点也需要记录,我们可以用"#"代表空节点,用","进行节点之间的分隔
序列化和反序列化可以用前序、后序和层次遍历,但是注意中序遍历序列化是不行的,不同的树中序序列化之后可能一样,同时也无法反序列化,因为无法知道根节点。比如如下两棵树:
1、为什么中序序列化不行
虽然两棵树并不一样,但是中序序列化的结果却一样。

前序序列化与反序列化的代码:

  1. public String serialize(TreeNode root) {
  2. if (root == null) {
  3. return "#,";
  4. }
  5. String result = root.val + ",";
  6. result += serialize(root.left);
  7. result += serialize(root.right);
  8. return result;
  9. }
  10. public TreeNode deserialize(String data) {
  11. if (data == null || data.isEmpty()) {
  12. return null;
  13. }
  14. Queue<String> nodes = new LinkedList<>();
  15. for (String str : data.split(",")) {
  16. if (!str.isEmpty()) {
  17. nodes.add(str);
  18. }
  19. }
  20. return deserialize(nodes);
  21. }
  22. // 反序列化递归的关键相信递归函数,我们每次从队列中取出头元素构造根节点,剩下的子树构造交给递归函数去解决
  23. private TreeNode deserialize(Queue<String> nodes) {
  24. if (nodes.isEmpty()) {
  25. return null;
  26. }
  27. String str = nodes.poll();
  28. if ("#".equals(str)) {
  29. return null;
  30. }
  31. int val = Integer.parseInt(str);
  32. TreeNode root = new TreeNode(val);
  33. root.left = deserialize(nodes);
  34. root.right = deserialize(nodes);
  35. return root;
  36. }

后续序列化与反序列化的代码:

  1. public String serialize(TreeNode root) {
  2. if (root == null) {
  3. return ",#";
  4. }
  5. String result = "";
  6. result += serialize(root.left);
  7. result += serialize(root.right);
  8. return result + "," + root.val;
  9. }
  10. public TreeNode deserialize(String data) {
  11. if (data == null || data.isEmpty()) {
  12. return null;
  13. }
  14. Stack<String> nodes = new Stack<>();
  15. for (String str : data.split(",")) {
  16. if (!str.isEmpty()) {
  17. nodes.push(str);
  18. }
  19. }
  20. return deserialize(nodes);
  21. }
  22. public TreeNode deserialize(Stack<String> nodes) {
  23. if (nodes.isEmpty()) {
  24. return null;
  25. }
  26. String str = nodes.pop();
  27. if ("#".equals(str)) {
  28. return null;
  29. }
  30. int val = Integer.parseInt(str);
  31. TreeNode root = new TreeNode(val);
  32. // 后序遍历要先右子树,再左子树
  33. root.right = deserialize(nodes);
  34. root.left = deserialize(nodes);
  35. return root;
  36. }

层次序列化和反序列化:

  1. public String serialize(TreeNode root) {
  2. if (root == null) {
  3. return null;
  4. }
  5. Queue<TreeNode> nodes = new LinkedList<>();
  6. nodes.add(root);
  7. StringBuilder sb = new StringBuilder();
  8. while (!nodes.isEmpty()) {
  9. TreeNode current = nodes.poll();
  10. if (current == null) {
  11. sb.append("#,");
  12. continue;
  13. }
  14. sb.append(current.val).append(",");
  15. nodes.add(current.left);
  16. nodes.add(current.right);
  17. }
  18. return sb.toString();
  19. }
  20. public TreeNode deserialize(String data) {
  21. if (data == null || data.isEmpty()) {
  22. return null;
  23. }
  24. String[] nodes = data.split(",");
  25. return deserialize(nodes);
  26. }
  27. private TreeNode deserialize(String[] nodes) {
  28. if (nodes == null || nodes.length == 0 || "#".equals(nodes[0])) {
  29. return null;
  30. }
  31. Queue<TreeNode> queue = new LinkedList<>();
  32. TreeNode root = new TreeNode(Integer.parseInt(nodes[0]));
  33. queue.add(root);
  34. int i = 1;
  35. while (i < nodes.length - 1 && !queue.isEmpty()) {
  36. TreeNode current = queue.poll();
  37. String leftStr = nodes[i++];
  38. if ("#".equals(leftStr)) {
  39. current.left = null;
  40. } else {
  41. TreeNode left = new TreeNode(Integer.parseInt(leftStr));
  42. current.left = left;
  43. queue.add(left);
  44. }
  45. String rightStr = nodes[i++];
  46. if ("#".equals(rightStr)) {
  47. current.right = null;
  48. } else {
  49. TreeNode right = new TreeNode(Integer.parseInt(rightStr));
  50. current.right = right;
  51. queue.add(right);
  52. }
  53. }
  54. return root;
  55. }

顺便提一下,leetcode中的树都是用层次序列化的方式存储的

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注