赞
踩
序列化二叉树
题目描述:
1.将二叉树以一定的规则(先序、中序、后续、层序)进行遍历,将节点数据保存到字符串中,每个节点数据保存到字符串中用"!“分割,空节点用”#"代替。
2.将得到的字符串按照一定的规则(先序、中序、后续、层序)构建二叉树。
题解
对于第一题,本文以层序遍历为例进行讲解:
层序遍历二叉树,首先考虑使用什么工具保存遍历的到的数据,层序遍历是从根节点开始,每层从左到右依次访问,直至遍历整个二叉树,其中最适合的便是队列,先进先出。
对于第一题的解题思路与代码,我详细的加到了代码段中,如下所示:
//这是定义二叉树的结构体,以及构造函数
struct TreeNode {
int val;
struct TreeNode *left;
struct TreeNode *right;
TreeNode(int x) :
val(x), left(NULL), right(NULL) {
}
};
char* Serialize(TreeNode *root) { //定义结构体类型的队列,用来存储得到的二叉树节点数据 queue<TreeNode*> q; //定义一个字符串,保存遍历的节点数据 string s; //使用层序遍历得到字符串 //由于节点为空需要返回#,因此需要考虑为空的情况 //首先,根节点进队 q.push(root); //循环的进队和出队操作,直到队列为空结束循环 while (!q.empty()) { //将队头出队 TreeNode *head = q.front(); //删除队头的元素 q.pop(); //判断出队的是个空节点,还是有左右子节点,有左右子节点的话需要对左右子节点进队操作 //为空的情况 if (head == nullptr) { s.push_back('#'); s.push_back('!'); continue; } //不为空的情况,把存取的数据提出来 s = s + to_string(head->val); s.push_back('!'); //有左子树 q.push(head->left); //有右子树 q.push(head->right); } //函数是char类型,最后需要把string转换为char char *str = new char[s.length() + 1]; strcpy(str, s.c_str()); return str; }
对于第二个题目,本文仍然使用层序遍历,但不同于直接构造二叉树的是需要对字符串进行分割,按照第一个题目中的分割标记"!",将字符串中的数字取出转换为整数类型,然后才能给节点赋值数据。
TreeNode* Deserialize(char *str) { //拷贝一个串备用,别后面把值改没了 string ss(str); //搞一个二叉树节点类型的队列,存储恢复出来的节点 queue<TreeNode *>node; //重构二叉树要确定两个标志,#和! //先看一下字符串是否为空 if (str == nullptr)return nullptr; //确定返回的字符串是不是有根节点,没有根节点同样为空 if (str[0] == '#')return nullptr; //程序能到这里就说明返回的字符串不为空,可以构建二叉树 //首先,构建二叉树的根节点,开始还在考虑如何依据结束符取值,没想到c++有可以用的函数 //接用构造函数直接初始化 //atoi(s.c_str())直接取出第一个!号之前的数组,省时省力。 TreeNode *root = new TreeNode(atoi(ss.c_str())); //既然前面的已经赋值,可以舍取,得到除去第一个节点值的剩下值 ss = ss.substr(ss.find_first_of('!') + 1); //根节点进队 node.push(root); //只要字符串不为空,就循环处理吧,至于后面那个条件暂时没看明白 while (!ss.empty() && !node.empty()) { TreeNode *temp = node.front(); node.pop(); //这里就不用判断字符串是不是空了,要是空的他也进不来 //根节点没有左子树 if (ss[0] == '#') { temp->left = nullptr; //里面放2是为了跳过结束标识符 ss = ss.substr(2); } else { //把左子树进队 temp->left = new TreeNode(atoi(ss.c_str())); node.push(temp->left); ss = ss.substr(ss.find_first_of('!') + 1); } //处理右子树的情况 if (ss[0] == '#') { temp->right = nullptr; ss = ss.substr(2); } else { temp->right = new TreeNode(atoi(ss.c_str())); node.push(temp->right); ss = ss.substr(ss.find_first_of('!') + 1); } } return root; }
代码可以直接copy,在主函数中调用即可,主要是理解层序遍历的原理。目前我也在学习的路上探索,如果有理解错误的地方,希望看到的大佬能给本文指出,我一定抓紧改正。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。