37.序列化二叉树

请实现两个函数,分别用来序列化和反序列化二叉树

解析:

 1. 对于序列化:使用前序遍历,递归的将二叉树的值转化为字符,并且在每次二叉树的结点

不为空时,在转化val所得的字符之后添加一个' , '作为分割。对于空节点则以 '#' 代替。

 2. 对于反序列化:按照前序顺序,递归的使用字符串中的字符创建一个二叉树(特别注意:

在递归时,递归函数的参数一定要是char ** ,这样才能保证每次递归后指向字符串的指针会

随着递归的进行而移动!!!)

/*
struct TreeNode {
    int val;
    struct TreeNode *left;
    struct TreeNode *right;
    TreeNode(int x) :
            val(x), left(NULL), right(NULL) {
    }
};
*/
class Solution {
public:
    char* Serialize(TreeNode *root) 
{
	if (!root)return nullptr;
	string s;
	Serialize1(root, s);
	char *res = new char[s.length() + 1];//这块不是()而是[]
	int i;
	for ( i= 0;i <int( s.length());i++)
	{
		res[i] = s[i];
	}
	res[i] = '\0';
	return res;
}

void Serialize1(TreeNode *root,string &str)
{
	if (root == NULL)
	{
		str += '#';
        return;
	}
    string s = to_string(root->val) ;
    s += ',';
	str+=s;
	Serialize1(root->left,str);
	Serialize1(root->right,str);
}


TreeNode* Deserialize(char *str) 
{
	if (str == NULL)return NULL;
	TreeNode *res = Deserialize1(&str);
	return res;
}

TreeNode* Deserialize1(char **str)//由于递归时,会不断的向后读取字符串,所以一定要用**str,以保证得到递归后指针str指向未被读取的字符
{
	if ((**str) == '#')
	{
        (*str)++;
		return NULL;
	}
	int num = 0;
	while ((**str)!=','&& (**str) != '\0')
	{
		num = num * 10 + ((**str) - '0');
		(*str)++;
	}
	TreeNode* res = new TreeNode(num);
	if ((**str)=='\0')return res;
	else (*str)++;
	res->left = Deserialize1(str);
	res->right = Deserialize1(str);
	return res;
}
};

 

为什么要用二级指针:


可以用一级指针,但是需要用一级指针的引用才行,一级指针的引用和二级指针一回事。比如说你有个数组指针 int *num,这个num现在指向数组第3个元素,你在函数调用的时候,如果在函数参数传入num的话,你在函数调用里面对num进行++操作,只会影响到这个函数里面,这个函数外面,num的指向的值还是第三个元素。我们想要函数调用结束后,在函数里面的num++操作会影响到函数外面,则1,可以使用指针的引用。2,使用二级指针,3使用一个全局变量统计num指向第几个元素的信息。

树的存储与遍历: 1.初始化二叉树 ```c++ #include <iostream> using namespace std; struct TreeNode { int val; TreeNode* left; TreeNode* right; TreeNode(int x) : val(x), left(NULL), right(NULL) {} }; TreeNode* createTree() { int val; cin >> val; if (val == -1) { return NULL; } TreeNode* root = new TreeNode(val); root->left = createTree(); root->right = createTree(); return root; } ``` 2.先序遍历二叉树 ```c++ void preOrder(TreeNode* root) { if (root == NULL) { return; } cout << root->val << " "; preOrder(root->left); preOrder(root->right); } ``` 3.中序遍历二叉树 ```c++ void inOrder(TreeNode* root) { if (root == NULL) { return; } inOrder(root->left); cout << root->val << " "; inOrder(root->right); } ``` 4.后序遍历二叉树 ```c++ void postOrder(TreeNode* root) { if (root == NULL) { return; } postOrder(root->left); postOrder(root->right); cout << root->val << " "; } ``` 5.销毁二叉树 ```c++ void destroyTree(TreeNode* root) { if (root == NULL) { return; } destroyTree(root->left); destroyTree(root->right); delete root; } ``` 二叉树的复原: 1.由前序、中序序列确定复原二叉树 ```c++ TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) { if (preorder.empty() || inorder.empty()) { return NULL; } int rootVal = preorder[0]; TreeNode* root = new TreeNode(rootVal); vector<int>::iterator it = find(inorder.begin(), inorder.end(), rootVal); int leftSize = it - inorder.begin(); vector<int> leftPreorder(preorder.begin() + 1, preorder.begin() + 1 + leftSize); vector<int> leftInorder(inorder.begin(), it); vector<int> rightPreorder(preorder.begin() + 1 + leftSize, preorder.end()); vector<int> rightInorder(it + 1, inorder.end()); root->left = buildTree(leftPreorder, leftInorder); root->right = buildTree(rightPreorder, rightInorder); return root; } ``` 2.由中序、后序序列确定复原二叉树 ```c++ TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) { if (inorder.empty() || postorder.empty()) { return NULL; } int rootVal = postorder.back(); TreeNode* root = new TreeNode(rootVal); vector<int>::iterator it = find(inorder.begin(), inorder.end(), rootVal); int leftSize = it - inorder.begin(); vector<int> leftInorder(inorder.begin(), it); vector<int> leftPostorder(postorder.begin(), postorder.begin() + leftSize); vector<int> rightInorder(it + 1, inorder.end()); vector<int> rightPostorder(postorder.begin() + leftSize, postorder.end() - 1); root->left = buildTree(leftInorder, leftPostorder); root->right = buildTree(rightInorder, rightPostorder); return root; } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值