LintCode 二叉樹的序列化和反序列化 題解

二叉樹的序列化和反序列化 


  設計一個算法,並編寫代碼來序列化和反序列化二叉樹。將樹寫入一個文件被稱爲“序列化”,讀取文件後重建同樣的二叉樹被稱爲“反序列化”。

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

 注意事項

There is no limit of how you deserialize or serialize a binary tree, LintCode will take your output of serialize as the input of deserialize, it won't check the result of serialize.

樣例

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

  3
 / \
9  20
  /  \
 15   7

我們的數據是進行BFS遍歷得到的。當你測試結果wrong answer時,你可以作爲輸入調試你的代碼。

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


解題思想:

本題的主要思想是進行層次遍歷。

1.首先對二叉樹進行層次遍歷,對於NULL的節點用字符#表示,每一個節點直接使用,進行分割

2.所以序列化後的二叉樹輸出的字符串data應該形如:string data = "1,2,3,#,#,4,5,#,#,6,7";

3.反序列化的思想同樣是這樣,首先將string分割成一個個的節點集合vector<string> tree,對於非NULL節點插入到一個execute隊列中,插入到隊列同時刪除tree中對應節點。

4.每次處理execute隊列的隊首元素,從tree中取出前兩個元素分別作爲左右子節點,tree中刪除前兩個元素,對於不是#的元素,將其插入到execute隊列中;對於是#的元素不操作。

5.重複第4步,直到execute隊列爲空。


/**
 * Definition of TreeNode:
 * class TreeNode {
 * public:
 *     int val;
 *     TreeNode *left, *right;
 *     TreeNode(int val) {
 *         this->val = val;
 *         this->left = this->right = NULL;
 *     }
 * }
 */
 

class Solution {
public:
    /**
     * This method will be invoked first, you should design your own algorithm 
     * to serialize a binary tree which denote by a root node to a string which
     * can be easily deserialized by your own "deserialize" method later.
     */
    string serialize(TreeNode *root) {            //序列化
	// write your code here
	string data = "";
	if (root == NULL)
		return data;

	vector<TreeNode*> queue;
	queue.push_back(root);
	// 將二叉樹的個節點按照從上到下、從左到有的存儲在queue中
	for (int i = 0; i<queue.size(); i++) {
		TreeNode* q = queue[i];
		if (q == NULL)
			continue;
		queue.push_back(q->left);
		queue.push_back(q->right);
	}
	for (int i = 0; i<queue.size(); i++)
	{
		TreeNode* tem = queue[i];
		if (tem != NULL)
		{
			char t[256];
			string s;

			sprintf(t, "%d", tem->val);
			s = t;
			data += (s + ",");
		}
		else
		{
			data += "#,";
		}
	}

	return data;

}


TreeNode *deserialize(string data) {         //反序列化
	// write your code here
	if (data == "")
		return NULL;

	vector<string> tree = split(data, ",");  //分割得到每一個節點
	queue<TreeNode*> execute;               //待插入子樹的節點隊列


	TreeNode * root = (TreeNode*)malloc(sizeof(TreeNode));//創建根節點
	root->left = root->right = NULL;
	root->val = atoi(tree[0].c_str());

	tree.erase(tree.begin());
	TreeNode* p = root;
	execute.push(p);



	while (execute.size() != 0)
	{
		if (tree.size()<2)
			break;


		TreeNode* cur = execute.front();
		execute.pop();
		if (tree[0] != "#")          //處理左子樹
		{
			TreeNode* tem = (TreeNode*)malloc(sizeof(TreeNode));
			tem->val = atoi(tree[0].c_str());
			tem->left = tem->right = NULL;
			cur->left = tem;
			execute.push(tem);     //左節點不是NULL,所以需要插入到隊列中,準備插入其自己的左右子節點
			tree.erase(tree.begin());   //刪除tree中該節點表示該節點已經處理過了

		}
		else
		{
			tree.erase(tree.begin()); //如果cur的左節點是NULL,直接刪除Tree中的該節點表示已經處理就好了。
		}

		if (tree[0] != "#")         //處理右子樹
		{
			TreeNode* tem = (TreeNode*)malloc(sizeof(TreeNode));
			tem->val = atoi(tree[0].c_str());
			tem->left = tem->right = NULL;
			cur->right = tem;
			execute.push(tem);
			tree.erase(tree.begin());
		}
		else
		{
			tree.erase(tree.begin());
		}

	}

	return root;

}
};


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章