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

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

// Your Codec object will be instantiated and called as such:
// Codec ser, deser;
// TreeNode* ans = deser.deserialize(ser.serialize(root));

class Codec {
public:

	// Encodes a tree to a single string.
	string serialize(TreeNode* root) {
		string s;
		if(!root) {
			return s;
		}
		
		queue q;
		TreeNode* tmp;
		TreeNode* tmp1;
		q.push(root);

		while(!q.empty()){
			tmp = q.front();
			q.pop();
			if(tmp->val != -2147483648) {
				s.append(to_string(tmp->val));
				s.append(",");
			} else {
				delete(tmp);
				s.append("#,");
				continue;
			}

			if(tmp->left) {
				q.push(tmp->left);
			} else {
				tmp1 = new TreeNode(-2147483648);
				q.push(tmp1);
			}
			
			if(tmp->right) {
				q.push(tmp->right);
			} else {
				tmp1 = new TreeNode(-2147483648);
				q.push(tmp1);
			}
		}
		
		return s;
	}

    // Decodes your encoded data to tree.
    TreeNode* deserialize(string data) {
		vector v; // 用v模拟队列
		TreeNode* root = NULL;
        if(data.length() <= 1)
			return NULL;

		int start = 0;
		int end = 0;

		int curVectorNodeIndex = 0;
		TreeNode* curDataNode = NULL;
		int childNum = 0; // 0 是左孩子,1是右孩子,2 是下一个节点

		int tmp;
		int i;
		
		// 确保 v 中有一个元素
		end = (int)data.find(',', start);
		start = end + 1;
		if(data[end-1] == '#')
			return NULL;

		root = new TreeNode(atoi((data.substr(0, end)).c_str()));
		curVectorNodeIndex = 0;
		v.push_back(root);
		
		// 遍历下一层的每个结点,用来确保将左右孩子赋值给当前层
		// 下一层的元素个数=当前层的元素实体个数的2倍
		while(start < data.length()) {
			// size_type m
			end = (int)data.find(',', start);

			if(data[end-1] != '#') {
				// data中遍历到的结点是实体结点

				curDataNode = new TreeNode(atoi((data.substr(start, end-start)).c_str()));
				v.push_back(curDataNode);
				
				// 做亲子鉴定
				if(childNum == 0) {
					v[curVectorNodeIndex]->left = curDataNode;
					childNum++;
				} else if(childNum == 1) {
					v[curVectorNodeIndex]->right = curDataNode;
					
					childNum = 0;
					curVectorNodeIndex++;
				}
			} else {
				// data中遍历到的结点是空结点

				if(childNum == 0) {
					v[curVectorNodeIndex]->left = NULL;
					childNum++;
				} else if(childNum == 1) {
					v[curVectorNodeIndex]->right = NULL;
					
					childNum = 0;
					curVectorNodeIndex++;
				}
			}

			start = end + 1;
		}
		
		return v[0];
    }
};

1 2 4 4 4
1 2 3 # # 4 5 6 7 # # # # 8 #

leetcode 297. 二叉树的序列化与反序列化_第1张图片
按层次序列化为:
1,2,3,#,#,4,5,#,#,#,#,
再反序列化:
用如下方式递进data:

		while(start < data.length()) {
			// size_type m
			end = (int)data.find(',', start);
			... ...
			start = end + 1;
		}

然后while中遍历的是当前层的节点
vector v 和 curVectorNodeIndex 指向的是当前遍历到节点对应的父结点
因为还要修改父结点的左右孩子指针,因此需要用vector来存储前面层的结点
curVectorNodeIndex 前进的条件是 父节点的右孩子赋值完毕
父节点的修改和子结点的遍历同步进行

附一段打印函数
void printTree(TreeNode* root){
	if(!root)
		return;

	queue q;
	TreeNode* tmp, *tmp1;
	q.push(root);

	while(!q.empty()){
		tmp = q.front();
		q.pop();
		if (tmp->val != -2147483648)
			cout << tmp->val << " ";
		else {
			cout <<"# ";
			delete tmp;
			continue;
		}

		if(tmp->left) {
			q.push(tmp->left);
		} else {
			tmp1 = new TreeNode(-2147483648);
			q.push(tmp1);
		}
		
		if(tmp->right) {
			q.push(tmp->right);
		} else {
			tmp1 = new TreeNode(-2147483648);
			q.push(tmp1);
		}
	}

你可能感兴趣的:(算法,leetcode,算法)