学习笔记—二叉树的序列化和反序列化

二叉树的序列化,如下所示二叉树的前序序列化为:1_2_4_#_#_5_#_#_3_6_#_#_7_#_#,其中#可以用于表示NULL

学习笔记—二叉树的序列化和反序列化_第1张图片

一、实现前序序列化代码

代码很简单,和前序遍历差不多,最后返回一个string类型的字符串

//先序遍历序列化
string serialBypre(TreeNode* root) {
	if (root == NULL)
		return "#_";
	string res = to_string(root->val) + "_";//to_string实现将int类型转换为string类型
	res += serialBypre(root->left);
	res += serialBypre(root->right);
	return res;
}

实现前序序列的反序列化:就是根据序列化的string重构出一个二叉树来,也就是创建二叉树,遇到“#”表示到达叶子节点

实现代码:

//反序列化
TreeNode* rebuildTree(queue& q) {//需要注意这个地方一定要用队列的引用,具体没想明白,坑了我一个小时
	string value = q.front();
	q.pop();
	if (value == "#")
		return NULL;
	TreeNode* head = new TreeNode(atoi(value.c_str()));//注意这个地方了,value是string类型
	head->left = rebuildTree(q);
	head->right = rebuildTree(q);
	return head;
}

其中上面的string类型传入为 124##5##36##7##,那么就需要一个split函数从1_2_4_#_#_5_#_#_3_6_#_#_7_#_#返回124##5##36##7##参考连接:https://blog.csdn.net/Li_haiyu/article/details/94469488

//split函数
void split(const string& str, const string& delim, queue& q)
{
	size_t front = 0;
	size_t back = str.find_first_of(delim, front);
	while (back != string::npos)
	{
		q.push(str.substr(front, back - front));
		front = back + 1;
		back = str.find_first_of(delim, front);
	}
	if (back - front > 0)
	{
		q.push(str.substr(front, back - front));
	}
}

测试代码:

#include
#include
#include
#include
#include
#include
using namespace std;
class TreeNode{
public:
	int val;
	TreeNode* left;
	TreeNode* right;
	TreeNode(int x) :val(x), left(NULL), right(NULL){
	}
};
//递归版本的
void PreOrder(TreeNode* root) {
	if (root != NULL) {
		cout << root->val << ' ';
		PreOrder(root->left);
		PreOrder(root->right);
	}
}
//非递归版本
void preOrder(TreeNode* root) {
	TreeNode* p = root;
	if (p != NULL) {
		stack s;
		s.push(p);
		while (!s.empty()) {
			p = s.top();
			s.pop();
			cout << p->val << ' ';
			if (p->right != NULL)
				s.push(p->right);
			if (p->left != NULL)
				s.push(p->left);
		}
	}
}
TreeNode* creatTreeNode()
{
	TreeNode *p;
	int data;
	cin >> data;
	if (data == -1)
		p = NULL;
	else
	{
		p = new TreeNode(data);
		p->left = creatTreeNode();
		p->right = creatTreeNode();
	}
	return p;
}
template
void display(vector v) {
	for (int i = 0; i < v.size(); ++i)
		cout << v[i];
	cout << endl;
}
//split函数
void split(const string& str, const string& delim, vector& ret)
{
	size_t front = 0;
	size_t back = str.find_first_of(delim, front);
	while (back != string::npos)
	{
		ret.push_back(str.substr(front, back - front));
		front = back + 1;
		back = str.find_first_of(delim, front);
	}
	if (back - front > 0)
	{
		ret.push_back(str.substr(front, back - front));
	}
}
//先序遍历序列化
string serialBypre(TreeNode* root) {
	if (root == NULL)
		return "#_";
	string res = to_string(root->val) + "_";//to_string实现将int类型转换为string类型
	res += serialBypre(root->left);
	res += serialBypre(root->right);
	return res;
}
//反序列化
TreeNode* rebuildTree(queue& q) {//需要注意这个地方一定要用队列的引用,具体没想明白,坑了我一个小时
	string value = q.front();
	q.pop();
	if (value == "#")
		return NULL;
	TreeNode* head = new TreeNode(atoi(value.c_str()));//注意这个地方了,value是string类型
	head->left = rebuildTree(q);
	head->right = rebuildTree(q);
	return head;
}
int main() {
	TreeNode* p = creatTreeNode();
	string s = serialBypre(p);
	cout << s << endl;
	vector vetnum;
	split(s, "_", vetnum);
	display(vetnum);
	queue q;
	for (int i = 0;i < vetnum.size(); ++i)
		q.push(vetnum[i]);
	TreeNode* recover = rebuildTree(q);
	//PreOrder(recover);
	preOrder(recover);
	while (1);
}

测试结果: 

 学习笔记—二叉树的序列化和反序列化_第2张图片

二、从上到下从到右实现二叉树的序列化

这个其实和从上到下从左到右打印二叉树的实现方法类似,可以参考链接:https://blog.csdn.net/Li_haiyu/article/details/93601806

从上到下从做到右打印的代码如下:

vector PrintFromTopToBottom(TreeNode* root) {
       vector v;
        TreeNode* p = root;
        if(p!=NULL){
            queue q;
            q.push(p);
            while(!q.empty()){
                p = q.front();
                q.pop();
                v.push_back(p->val);
                if(p->left!=NULL){
                    q.push(p->left);
                }
                if(p->right!=NULL){
                    q.push(p->right);
                }
            }
        }
        return v;
    }

从上到下从做到右序列化的代码如下 

//按照从上到下左到右的方式序列化
string serial_up_to_down(TreeNode* root) {
	TreeNode* p = root;
	string s = "";
	if (p != NULL) {
		queue < TreeNode*> q;
		q.push(p);
		while (!q.empty()) {
			p = q.front();
			q.pop();
			s += to_string(p->val);
			s += "_";
			if (p->left != NULL)
				q.push(p->left);
			else
				s+= "#_";
			if (p->right != NULL)
				q.push(p->right);
			else
				s += "#_";
		}
	}
	return s;
}

完整测试代码:

#include
#include
#include
#include
using namespace std;
class TreeNode{
public:
	int val;
	TreeNode* left;
	TreeNode* right;
	TreeNode(int x) :val(x), left(NULL), right(NULL){
	}
};
TreeNode* creatTreeNode()
{
	TreeNode *p;
	int data;
	cin >> data;
	if (data == -1)
		p = NULL;
	else
	{
		p = new TreeNode(data);
		p->left = creatTreeNode();
		p->right = creatTreeNode();
	}
	return p;
}
template
void display(vector v) {
	for (int i = 0; i < v.size(); ++i)
		cout << v[i];
	cout << endl;
}
vector split_find(const string &str,const string &patten) {
	vector res;
	if (str != "") {
		string strs = str + patten;//在字符串末尾也加入分隔符,方便截取最后一段
		size_t pos = strs.find(patten);//find函数返回的是其下标
		while (pos != string::npos) {//使用循环将每一段都存放如vector中
			string temp = strs.substr(0, pos);
			res.push_back(temp);
			strs = strs.substr(pos + 1);//然后拷贝第一个分隔符后面的所有元素,循环
			pos = strs.find(patten);
		}
	}
	return res;
}
//按照从上到下左到右的方式序列化
string serial_up_to_down(TreeNode* root) {
	TreeNode* p = root;
	string s = "";
	if (p != NULL) {
		queue < TreeNode*> q;
		q.push(p);
		while (!q.empty()) {
			p = q.front();
			q.pop();
			s += to_string(p->val);
			s += "_";
			if (p->left != NULL)
				q.push(p->left);
			else
				s+= "#_";
			if (p->right != NULL)
				q.push(p->right);
			else
				s += "#_";
		}
	}
	return s;
}
//从上到下从左到右打印结果
vector PrintFromTopToBottom(TreeNode* root) {
	vector v;
	TreeNode* p = root;
	if (p != NULL) {
		queue q;
		q.push(p);
		while (!q.empty()) {
			p = q.front();
			q.pop();
			v.push_back(p->val);
			if (p->left != NULL) {
				q.push(p->left);
			}
			if (p->right != NULL) {
				q.push(p->right);
			}
		}
	}
	return v;
}
int main() {
	TreeNode* p = creatTreeNode();
	vector v = PrintFromTopToBottom(p);
	cout << "从上到下从左到右打印结果:";
	display(v);
	string s = serial_up_to_down(p);
	cout << "从上到下从左到右序列化结果:" << s << endl;
	while (1);
}

测试结果:

 

从上到下反序列化:不会。

 

你可能感兴趣的:(牛客算法)