1. 程式人生 > >[LintCode] Serialize and Deserialize Binary Tree(二叉樹的序列化和反序列化)

[LintCode] Serialize and Deserialize Binary Tree(二叉樹的序列化和反序列化)

描述

設計一個演算法,並編寫程式碼來序列化和反序列化二叉樹。將樹寫入一個檔案被稱為“序列化”,讀取檔案後重建同樣的二叉樹被稱為“反序列化”。

如何反序列化或序列化二叉樹是沒有限制的,你只需要確保可以將二叉樹序列化為一個字串,並且可以將字串反序列化為原來的樹結構。

對二進位制樹進行反序列化或序列化的方式沒有限制,LintCode將您的serialize輸出作為deserialize的輸入,它不會檢查序列化的結果。

樣例

給出一個測試資料樣例, 二叉樹{3,9,20,#,#,15,7},表示如下的樹結構:

  3
 / \
9  20
  /  \
 15   7

我們的資料是進行 BFS 遍歷得到的。當你測試結果 wrong answer時,你可以作為輸入除錯你的程式碼。

你可以採用其他的方法進行序列化和反序列化。

程式碼

GitHub 的原始碼,請訪問下面的連結:

https://github.com/cwiki-us/java-tutorial/blob/master/src/test/java/com/ossez/lang/tutorial/tests/lintcode/LintCode0007SerializeAndDeserialize.java

package com.ossez.lang.tutorial.tests.lintcode;

import java.util.ArrayList;

import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.ossez.lang.tutorial.models.TreeNode;

/**
 * <p>
 * 7
 * <ul>
 * <li>@see <a href=
 * "https://www.cwiki.us/display/ITCLASSIFICATION/Serialize+and+Deserialize+Binary+Tree">https://www.cwiki.us/display/ITCLASSIFICATION/Serialize+and+Deserialize+Binary+Tree</a>
 * <li>@see<a href=
 * "https://www.lintcode.com/problem/serialize-and-deserialize-binary-tree">https://www.lintcode.com/problem/serialize-and-deserialize-binary-tree</a>
 * </ul>
 * </p>
 * 
 * @author YuCheng
 *
 */
public class LintCode0007SerializeAndDeserialize {

  private final static Logger logger = LoggerFactory.getLogger(LintCode0007SerializeAndDeserialize.class);

  /**
   * 
   */
  @Test
  public void testMain() {
    logger.debug("BEGIN");
    String data = "{3,9,20,#,#,15,7}";

    System.out.println(serialize(deserialize(data)));

  }

  /**
   * Deserialize from array to tree
   * 
   * @param data
   * @return
   */
  private TreeNode deserialize(String data) {
    // NULL CHECK
    if (data.equals("{}")) {
      return null;
    }

    ArrayList<TreeNode> treeList = new ArrayList<TreeNode>();

    data = data.replace("{", "");
    data = data.replace("}", "");
    String[] vals = data.split(",");

    // INSERT ROOT
    TreeNode root = new TreeNode(Integer.parseInt(vals[0]));
    treeList.add(root);

    int index = 0;
    boolean isLeftChild = true;
    for (int i = 1; i < vals.length; i++) {
      if (!vals[i].equals("#")) {
        TreeNode node = new TreeNode(Integer.parseInt(vals[i]));
        if (isLeftChild) {
          treeList.get(index).left = node;
        } else {
          treeList.get(index).right = node;
        }
        treeList.add(node);
      }

      // LEVEL
      if (!isLeftChild) {
        index++;
      }

      // MOVE TO RIGHT OR NEXT LEVEL
      isLeftChild = !isLeftChild;
    }

    return root;

  }

  /**
   * 
   * @param root
   * @return
   */
  public String serialize(TreeNode root) {
    // write your code here
    if (root == null) {
      return "{}";
    }

    ArrayList<TreeNode> queue = new ArrayList<TreeNode>();
    queue.add(root);

    for (int i = 0; i < queue.size(); i++) {
      TreeNode node = queue.get(i);
      if (node == null) {
        continue;
      }
      queue.add(node.left);
      queue.add(node.right);
    }

    while (queue.get(queue.size() - 1) == null) {
      queue.remove(queue.size() - 1);
    }

    StringBuilder sb = new StringBuilder();
    sb.append("{");
    sb.append(queue.get(0).val);
    for (int i = 1; i < queue.size(); i++) {
      if (queue.get(i) == null) {
        sb.append(",#");
      } else {
        sb.append(",");
        sb.append(queue.get(i).val);
      }
    }
    sb.append("}");
    return sb.toString();
  }

}

 

 

點評

本題目主要需要你對二叉樹的遍歷方法有所瞭解。

遍歷二叉樹主要有 2 類方法,分別為深度優先(DFS)和廣度優先(BFS)。

在深度優先中,你有又可以使用前序,中序和後序搜尋方法,你可以使用遞迴或者非遞迴演算法實現。對於廣度優先演算法,一般都會採用非遞迴的實現方法進行實現。